def lsim(self, u, t, interp=0, returnall=False, X0=None): """Find the response of the TransferFunction to the input u with time vector t. Uses signal.lsim. return y the response of the system.""" if returnall:#most users will just want the system output y, #but some will need the (t, y, x) tuple that #signal.lsim returns return signal.lsim(self, u, t, interp=interp, X0=X0) else: return signal.lsim(self, u, t, interp=interp, X0=X0)[1]
def time_response(self, F, t, ic=None): r"""Time response for a mdof system. This method returns the time response for a mdof system given a force, time and initial conditions. Parameters ---------- F : array Force array (needs to have the same length as time array). t : array Time array. ic : array, optional The initial conditions on the state vector (zero by default). Returns ---------- t : array Time values for the output. yout : array System response. xout : array Time evolution of the state vector. Examples -------- >>> m1, m2 = 1, 1 >>> c1, c2, c3 = 1, 1, 1 >>> k1, k2, k3 = 1e3, 1e3, 1e3 >>> M = np.array([[m1, 0], ... [0, m2]]) >>> C = np.array([[c1+c2, -c2], ... [-c2, c2+c3]]) >>> K = np.array([[k1+k2, -k2], ... [-k2, k2+k3]]) >>> sys1 = VibSystem(M, C, K) # create the system >>> t = np.linspace(0, 25, 1000) # time array >>> F2 = np.zeros((len(t), 2)) >>> F2[:, 1] = 1000*np.sin(40*t) # force applied on m2 >>> t, yout, xout = sys1.time_response(F2, t) >>> yout[:5, 0] # response on m1 array([ 0. , 0.00304585, 0.07034816, 0.32048951, 0.60748282]) >>> yout[:5, 1] # response on m2 array([ 0. , 0.08160348, 0.46442657, 0.7885541 , 0.47808092]) """ if ic is not None: return signal.lsim(self.H, F, t, ic) else: return signal.lsim(self.H, F, t)
def test_nonzero_initial_time(self): system = self.lti_nowarn(-1.,1.,1.,0.) t = np.linspace(1,2) u = np.zeros_like(t) tout, y, x = lsim(system, u, t, X0=[1.0]) expected_y = np.exp(-tout) assert_almost_equal(y, expected_y)
def siggen_model(s, rad, phi, z, e, temp): out = np.zeros(sample_length) if temp < 40 or temp > 120: return np.ones(sample_length)*-1. detector.SetTemperature(temp) siggen_wf= detector.GetSiggenWaveform(rad, phi, z, energy=2600) if siggen_wf is None: return np.ones(sample_length)*-1. if np.amax(siggen_wf) == 0: print "wtf is even happening here?" return np.ones(sample_length)*-1. siggen_wf = np.pad(siggen_wf, (detector.zeroPadding,0), 'constant', constant_values=(0, 0)) tout, siggen_wf, x = signal.lsim(system, siggen_wf, t) siggen_wf /= np.amax(siggen_wf) siggen_data = siggen_wf[detector.zeroPadding::] siggen_data = siggen_data*e siggen_start_idx = np.int(np.around(s, decimals=1) * data_to_siggen_size_ratio % data_to_siggen_size_ratio) switchpoint_ceil = np.int( np.ceil(s) ) samples_to_fill = (sample_length - switchpoint_ceil) sampled_idxs = np.arange(samples_to_fill, dtype=np.int)*data_to_siggen_size_ratio+siggen_start_idx out[switchpoint_ceil:] = siggen_data[sampled_idxs] return out
def siggen_model(s, rad, phi, z, e, temp, gradIdx, pcRadIdx): out = np.zeros_like(data) if (gradIdx > detectorList.shape[0]-1) or (pcRadIdx > detectorList.shape[1]-1) : return np.ones_like(data)*-1. detector = detectorList[gradIdx, pcRadIdx] detector.SetTemperature(temp) siggen_wf= detector.GetSiggenWaveform(rad, phi, z, energy=2600) # print "len of siggen wf is %d" % len(siggen_wf) if siggen_wf is None: return np.ones_like(data)*-1. if np.amax(siggen_wf) == 0: print "wtf is even happening here?" return np.ones_like(data)*-1. siggen_wf = np.pad(siggen_wf, (detector.zeroPadding,0), 'constant', constant_values=(0, 0)) tout, siggen_wf, x = signal.lsim(system, siggen_wf, t) siggen_wf /= np.amax(siggen_wf) siggen_data = siggen_wf[detector.zeroPadding::] siggen_data = siggen_data*e out[s:] = siggen_data[0:(len(data) - s)] return out
def rhSCCDisplacement(angVel, time): radius = 3.2e-03 #define transfer function T1 = 0.01 #value from wikibook T2 = 5 #value from wikibook #aligne with reid's line rM_reid = thr.R2(-15) #define orientation and size of right horizontal semicircular canal, and turn it into space-fixed coordinates rhScc = np.array([0.32269,-0.03837,-0.94573]) rhSccSpace = rM_reid.dot(rhScc) #sensed angular velocity in right horizontal semicircular canal vel = angVel.dot(rhSccSpace) numerator = [T1*T2, 0] denominator = [T1*T2, T1+T2, 1] scc = ss.lti(numerator,denominator) #calculate system response of input using transfer function defined above timeOut,sysResponse,timeEvol = ss.lsim(scc,vel,time) #calculate the displacement of the cupula from the system response displacementCupula = sysResponse*radius return displacementCupula
def vestibularStimulation(self, sensor): '''Stimulation of canals and otoliths.''' # First for the angular velocity ----------------------- ReidangVel = rotmat.R2(15).dot(sensor.spaceAngVel.T) # sensed angular velocity omega = ReidangVel.T.dot(self.n_HorScc) # Canal dynamics tout, cupulaTheta, xout = ss.lsim(self.scc, omega, sensor.time) # Displacement maxima cupula = cupulaTheta * self.r_scc sensedMaxima = {} sensedMaxima['deflection_Max'] = max(cupula) sensedMaxima['deflection_Min'] = min(cupula) # Then for linear acceleration ---------------------------- onDir = np.array([0., 1., 0.]) accSensed = sensor.accReHead.dot(onDir) # Acceleration maxima sensedMaxima['acc_Max'] = max(accSensed) sensedMaxima['acc_Min'] = min(accSensed) return sensedMaxima
def siggen_model(s, rad, phi, z, e, temp): out = np.zeros_like(data) detector.SetTemperature(temp) siggen_wf= detector.GetSiggenWaveform(rad, phi, z, energy=2600) if siggen_wf is None: return np.ones_like(data)*-1. if np.amax(siggen_wf) == 0: print "wtf is even happening here?" return np.ones_like(data)*-1. siggen_wf = np.pad(siggen_wf, (detector.zeroPadding,0), 'constant', constant_values=(0, 0)) tout, siggen_wf, x = signal.lsim(system, siggen_wf, t) siggen_wf /= np.amax(siggen_wf) siggen_data = siggen_wf[detector.zeroPadding::] siggen_data = siggen_data*e #ok, so the siggen step size is 1 ns and the #WARNING: only works for 1 ns step size for now #TODO: might be worth downsampling BEFORE applying transfer function siggen_start_idx = np.int(np.around(s, decimals=1) * data_to_siggen_size_ratio % data_to_siggen_size_ratio) switchpoint_ceil = np.int( np.ceil(s) ) samples_to_fill = (len(data) - switchpoint_ceil) sampled_idxs = np.arange(samples_to_fill, dtype=np.int)*data_to_siggen_size_ratio+siggen_start_idx out[switchpoint_ceil:] = siggen_data[sampled_idxs] return out
def siggen_model(s, rad, phi, z, e, temp, num_1, num_2, num_3, den_1, den_2, den_3): out = np.zeros_like(data) detector.SetTemperature(temp) siggen_wf= detector.GetSiggenWaveform(rad, phi, z, energy=2600) if siggen_wf is None: return np.ones_like(data)*-1. if np.amax(siggen_wf) == 0: print "wtf is even happening here?" return np.ones_like(data)*-1. siggen_wf = np.pad(siggen_wf, (detector.zeroPadding,0), 'constant', constant_values=(0, 0)) num = [num_1, num_2, num_3] den = [1, den_1, den_2, den_3] # num = [-1.089e10, 5.863e17, 6.087e15] # den = [1, 3.009e07, 3.743e14,5.21e18] system = signal.lti(num, den) t = np.arange(0, len(siggen_wf)*10E-9, 10E-9) tout, siggen_wf, x = signal.lsim(system, siggen_wf, t) siggen_wf /= np.amax(siggen_wf) siggen_data = siggen_wf[detector.zeroPadding::] siggen_data = siggen_data*e out[s:] = siggen_data[0:(len(data) - s)] return out
def vestibularStimulation(self, sensor): '''Stimulation of canals and otoliths.''' # First for the angular velocity ----------------------- ReidangVel = np.dot(RotMat.R2(15), sensor.spaceAngVel.transpose()) # sensed angular velocity omega = np.dot(ReidangVel.transpose(), self.n_HorScc) # mpl.plot(sensor.time, omega) # mpl.show() # raw_input() # Canal dynamics tout, cupulaTheta, xout = ss.lsim(self.scc, omega, sensor.time) #mpl.hold #mpl.plot(tout, yout,'r') # Displacement maxima cupula = cupulaTheta * self.r_scc sensedMaxima = {} sensedMaxima['deflection_Max'] = max(cupula) sensedMaxima['deflection_Min'] = min(cupula) # Then for linear acceleration ---------------------------- onDir = np.array([0., 1., 0.]) accSensed = np.dot(sensor.accReHead, onDir) # Acceleration maxima sensedMaxima['acc_Max'] = max(accSensed) sensedMaxima['acc_Min'] = min(accSensed) return sensedMaxima
def _test_system(): """Test PID algorithm.""" import scipy.signal as sig # transfer function in s-space describes sys tf = sig.tf2ss([10], [100, 10]) times = np.arange(1, 200, 5.0) #step = 1 * np.ones(len(times)) # initialize PID pid = PidController(2.0, 10.0, 0.0) pid.anti_windup = 0.2 pid.vmin, pid.vmax = -200.0, 200.0 pid.setpoint = 50.0 pid._prev_time = 0.0 sysout = [0.0] pidout = [0.0] real_time = [0.0] for time in times: real_time.append(time) pidout.append(pid.compute_output(sysout[-1], real_time[-1])) t, sysout, xout = sig.lsim(tf, pidout, real_time) fig = plt.figure() ax = fig.add_subplot(111) ax.plot(real_time, sysout, 'r', real_time, pidout, 'b--') plt.show()
def exp_sin_respLTI(decay, zeta, freq, tvec): H = sp.lti([1], poly1d([1, 2 * zeta * 1.5, 2.25]).coeffs) u = cos(freq * tvec) * exp(-1 * decay * tvec) t, x, svec = sp.lsim(H, u, tvec) plot(t, x) title("Complete Response at " + str(freq) + "Hz") savefig("./Images/expsinLTI_" + str(freq) + ".png") close() return 0
def plot_response(system, u, t, name=""): _, y, _= signal.lsim(system, u, t) fig = go.Figure() fig.add_trace(go.Scatter(x=t, y=u, name="input")) fig.add_trace(go.Scatter(x=t, y=y, name="output")) fig.add_trace(go.Scatter(x=t, y=y-u, name="error")) fig.update_xaxes(title="Time (s)") fig.update_layout(title=name) fig.show()
def FoldedCascodeFilter(anInput, c1, c2, r): num = [c1*r,0] den = [c2*r, 1] system = signal.TransferFunction(num, den) t = np.arange(0, len(anInput)) tout, y, x = signal.lsim(system, anInput, t) return y
def test_integrator(self): # integrator: y' = u system = self.lti_nowarn(0., 1., 1., 0.) t = np.linspace(0,5) u = t tout, y, x = lsim(system, u, t) expected_x = 0.5 * tout**2 assert_almost_equal(x, expected_x) assert_almost_equal(y, expected_x)
def RLCFilter(anInput, rc, lc): num = [1] den = [lc, rc, 1] system = signal.TransferFunction(num, den) t = np.arange(0, len(anInput)) tout, y, x = signal.lsim(system, anInput, t) return y
def OpAmpFilter(anInput, r1, r2, c): num = [r2] den = [r1*r2*c, r1] system = signal.TransferFunction(num, den) t = np.arange(0, len(anInput)) tout, y, x = signal.lsim(system, anInput, t) return y
def calc_inverse_Al_dynamics(t, T_targ, K, t0, zeta, n_per=1): ''' Inverse of the second order dynamical model for tha Al cell Gives the temperature input required for a target temperature output t is the time signal (Assumes t is equally spaced!) The rest of the inputs are constants defining the dynamic response n_per is the number of repetitions. E.g., n_per = 10 will give the response after the input has already been applied 9 times Useful for approximating a periodic system ''' T_init = T_targ[0] # Extend over n_per periods if n_per > 1: T_targ_ext = np.concatenate([T_targ[:-1] for n in range(n_per)] + [T_targ[-1:]]) t_ext = np.concatenate([t[:-1] + n * t[-1] for n in range(n_per)] + [t[-1:] * n_per]) else: T_targ_ext = T_targ[:] t_ext = t[:] # Subtract initial value T_targ_ext -= T_init w0 = 2 * np.pi / t0 kz = K * zeta a = 1 / (kz * w0) b = (2 * kz * zeta - 1) / (kz**2) c = (kz**2 - 2 * kz * zeta + 1) * w0 / (kz**3) tau = kz / w0 # Derivative part dt = t[1] - t[0] #print(A, B, C, tau) T_der = a * np.gradient(T_targ_ext, dt, edge_order=2) # Gain part T_gain = b * T_targ_ext # Integral part num = [c] den = [1.0, 1.0 / tau] int_sys = sig.lti(num, den) t_int, T_int, x_out = sig.lsim(int_sys, T_targ_ext, t_ext) T_in = T_der + T_gain + T_int + T_init return T_in[-len(t):]
def test_first_order(self): # y' = -y # exact solution is y(t) = exp(-t) system = self.lti_nowarn(-1., 1., 1., 0.) t = np.linspace(0, 5) u = np.zeros_like(t) tout, y, x = lsim(system, u, t, X0=[1.0]) expected_x = np.exp(-tout) assert_almost_equal(x, expected_x) assert_almost_equal(y, expected_x)
def test_first_order(self): # y' = -y # exact solution is y(t) = exp(-t) system = self.lti_nowarn(-1.,1.,1.,0.) t = np.linspace(0,5) u = np.zeros_like(t) tout, y, x = lsim(system, u, t, X0=[1.0]) expected_x = np.exp(-tout) assert_almost_equal(x, expected_x) assert_almost_equal(y, expected_x)
def simulate(kp, ki, kd, time_arr, reference_arr, ax): a = 0.94 b = 9 c = 0.4 system = sig.lti([0, 0, b * kp, b * ki], [1, a + b * kd, c + b * kp, b * ki]) time_arr = np.linspace(9, 19.9, 500) reference_arr = [90 if x > 10 else 0 for x in time_arr] tout, response, _ = sig.lsim(system, reference_arr, time_arr, interp=0) return time_arr, response
def simulate(self, u: np.ndarray, t: np.ndarray) -> np.ndarray: """ Simulate filter :param u: filter input :param t: timeseries :return: filter output """ _, y, x = lsim(self.filter, U=u, T=t, X0=self.x) self.x = x[-1] return y
def graph_pid(kp, ki, kd, col): a = 0.94 b = 9 c = 0.4 system = sig.lti([0, 0, b * kp, b * ki], [1, a + b * kd, c + b * kp, b * ki]) time_arr = np.linspace(0, 10, 500) reference_arr = np.repeat(90, 500) tout, response, _ = sig.lsim(system, reference_arr, time_arr, interp=0) pp.plot(time_arr, response, color=(col, 0, 1 - col))
def apply_to_signal(self, signal_in): returning_signal = Signal(None) returning_signal.copy_signal(signal_in) if self.blockActivated: if 1 / signal_in.period <= 3.9: tout, y, ni = signal.lsim( (self.b1, self.a1), signal_in.yValues, signal_in.timeArray) returning_signal.set_x_y_values(tout, y) returning_signal.cut_first_period() elif 3510 >= 1 / signal_in.period > 3.9: tout, y, ni = signal.lsim( (self.b2, self.a2), signal_in.yValues, signal_in.timeArray) returning_signal.set_x_y_values(tout, y) returning_signal.cut_first_period() else: tout, y, ni = signal.lsim( (self.b3, self.a3), signal_in.yValues, signal_in.timeArray) returning_signal.set_x_y_values(tout, y) returning_signal.cut_first_period() return returning_signal
def ProcessWaveform(self, siggen_wf, outputLength, scale, switchpoint): '''Use interpolation instead of rounding''' siggen_len = self.num_steps #+ self.zeroPadding # #TODO: i don't think zero padding actually does anything anyway # if self.zeroPadding == 0: # zeroPaddingIdx = 0 # else: # siggen_wf = np.pad(siggen_wf, (self.zeroPadding,0), 'constant', constant_values=(0, 0)) # zeroPaddingIdx = self.zeroPadding #actual wf gen tout, siggen_data, x = signal.lsim(self.tfSystem, siggen_wf, self.time_steps) smax = np.amax(siggen_data) # if smax == 0: # print "waveform max is 0 -- something went wrong" # exit(0) siggen_data /= smax # siggen_data = siggen_wf[zeroPaddingIdx::] siggen_data *= scale #resample the siggen wf to the 10ns digitized data frequency w/ interpolaiton switchpoint_ceil = np.int(np.ceil(switchpoint)) samples_to_fill = (outputLength - switchpoint_ceil) siggen_interp_fn = interpolate.interp1d(np.arange(self.num_steps), siggen_data, kind="linear", copy="False", assume_sorted="True") siggen_start_idx = (switchpoint_ceil - switchpoint) * self.data_to_siggen_size_ratio sampled_idxs = np.arange( samples_to_fill) * self.data_to_siggen_size_ratio + siggen_start_idx out = np.zeros(outputLength) try: out[switchpoint_ceil:] = siggen_interp_fn(sampled_idxs) except ValueError: print "Something goofy happened here during interp" print outputLength print siggen_wf.size print sampled_idxs[-10:] return None return out
def sin_paNotch(): w, f, dB, phase, sys, w0 = pasa_alto_notch.pa_notch() A = float(input()) # amplitud del seno de mi señal w1 = float(input()) # frecuencia de mi señal t = np.linspace(0, 5, 500) u = A * np.sin(w1 * t) tout, y, x = signal.lsim(sys, u, t) plt.plot(t, y) plt.xlabel('seg') plt.ylabel('A (amplitud)') plt.grid() plt.show()
def processInput(self, inputSignal, loadingModel, fraction): actual = inputSignal tfList = tf.getTf() paso = fraction / len(tfList) for tfi in tfList: t, y, x = signal.lsim(tfi, actual.values, actual.xvar) actual = Senial(t, y) if loadingModel: loadingModel.update(paso) return actual
def RLC(time, inp=func, bode=False, R=100, L=1e-6, C=1e-6): H = sp.lti([1], [L * C, R * C, 1]) if bode: w, S, phi = H.bode() fig, (ax1, ax2) = plt.subplots(2, 1) ax1.set_title("Magnitude response") ax1.semilogx(w, S) ax2.set_title("Phase response") ax2.semilogx(w, phi) plt.show() return sp.lsim(H, inp(time), time)
def fullModel(IsPfc, angles, Rc, time): Is2Bpol2 = buildIs2BpolB(isttok_mag_2) RIc = isttok_mag['RM'] + isttok_mag['Rcopper'] * np.cos(anglesIc) ZIc = isttok_mag['Rcopper'] * np.sin(anglesIc) A2, Bs2, C2, Ds2 = buildLtiModelB(RIc, ZIc, isttok_mag_2, Rc) Ic2Bpol = buildIc2Bpol(RIc, ZIc) magSys2 = signal.StateSpace(A2, Bs2, C2, Ds2) bPolIs2 = np.matmul(Is2Bpol2, IsPfc) tout2, Ic2, x2 = signal.lsim(magSys2, IsPfc.T, time) bPolIc2 = np.matmul(Ic2Bpol, Ic2.T) bPolTot2 = (bPolIs2.T + bPolIc2.T) * 50 * 49e-6 return bPolTot2, (RIc, ZIc)
def grafSignal(self, sys2, w0): if senhal['senoide']: amp = senhalparams['Amplitud'] w1 = senhalparams['frecuencia'] t = np.linspace(0, 5, 500) u = amp * np.sin(w1 * t) tout, y, x = signal.lsim(sys2, u, t) self.ax1.plot(tout, y) self.ax1.set_xlabel('seg') self.ax1.set_ylabel('A (ammplitud)') self.ax1.grid(True) elif senhal['pulso']: amp = senhalparams['Amplitud'] t = np.linspace(0, 5 * (1 / w0), 5000) u = amp * (np.sign(t) + 1) tout, y, x = signal.lsim(sys2, u, t) self.ax1.plot(tout, y) self.ax1.set_xlabel('seg') self.ax1.set_ylabel('A (ammplitud)') self.ax1.grid(True) else: amp = senhalparams['Amplitud'] duty = senhalparams['DutyCicle'] f1 = senhalparams['frecuencia'] w1 = f1 * 2 * np.pi t = np.linspace(0, 2, 500) u = amp * signal.square(2 * np.pi * w1 * t, duty) tout, y, x = signal.lsim(sys2, u, t) self.ax1.plot(tout, y) self.ax1.set_xlabel('seg') self.ax1.set_ylabel('A (ammplitud)') self.ax1.grid(True)
def rspect(A, z, fs): """ by Omar A: Señal de acceleraciones z: amortiguamiento fs: Frecuencia de adqusición o muestreo """ # ¿Qué es T? T = [(x * 1 / fs) for x in range(0, len(A))] # Pseudo acceleration response spectrum Pa = [] # Oscilator periods for start=0.0,stop=4.0,step=0.02 Ts = spec_period_serie() for i in range(len(Ts)): t = Ts[i] wn = (2.0 * numpy.pi) / t # H = sg.TransferFunction(num=[0.0, 0.0, -1.0], den=[1.0, 2.0*z*wn, wn**2]) # H2 = sg.TransferFunction(num=[-1.0, 0.0, 0.0], den=[1.0, 2.0*z*wn, wn**2]) H = sg.TransferFunction([-1.0, 0.0, 0.0], [wn, 2.0 * z * wn, 1.0]) H2 = sg.TransferFunction([0.0, 0.0, -1.0], [wn, 2.0 * z * wn, 1.0]) # tout, a 1D array, time values for the output # yout, 1D array system response # xout, time evolution of the state vector # displacement response Tout, Yout, Xout = sg.lsim(system=H, U=A, T=T) # acceleration response Tout1, Yout1, Xout1 = sg.lsim(system=H2, U=A, T=T) D = max(map(lambda x: abs(x), Yout)) EA = max(map(lambda x: abs(x), Yout1)) # No sé donde se usa esta variable Pa.append(D * (2 * numpy.pi / Ts[i])**2 / 9.81) # ¿Es acceleración o desplazamiento? return Ts, Pa
def test_double_integrator(self): # double integrator: y'' = 2u A = np.mat("0. 1.; 0. 0.") B = np.mat("0.; 1.") C = np.mat("2. 0.") system = self.lti_nowarn(A, B, C, 0.) t = np.linspace(0, 5) u = np.ones_like(t) tout, y, x = lsim(system, u, t) expected_x = np.transpose(np.array([0.5 * tout**2, tout])) expected_y = tout**2 assert_almost_equal(x, expected_x) assert_almost_equal(y, expected_y)
def get_output_with_lsim(H, x, t): simplH = simplify(H) num = fraction(simplH)[0] den = fraction(simplH)[1] num2, den2 = get_numpy_array_from_Poly(num, den) num2 = np.poly1d(num2) den2 = np.poly1d(den2) H = sp.lti(num2, den2) t, y, sec = sp.lsim(H, x, t) return t, y
def test_double_integrator(self): # double integrator: y'' = 2u A = matrix([[0., 1.], [0., 0.]]) B = matrix([[0.], [1.]]) C = matrix([[2., 0.]]) system = self.lti_nowarn(A, B, C, 0.) t = np.linspace(0, 5) u = np.ones_like(t) tout, y, x = lsim(system, u, t) expected_x = np.transpose(np.array([0.5 * tout**2, tout])) expected_y = tout**2 assert_almost_equal(x, expected_x) assert_almost_equal(y, expected_y)
def test_double_integrator(self): # double integrator: y'' = 2u A = np.mat("0. 1.; 0. 0.") B = np.mat("0.; 1.") C = np.mat("2. 0.") system = self.lti_nowarn(A, B, C, 0.) t = np.linspace(0,5) u = np.ones_like(t) tout, y, x = lsim(system, u, t) expected_x = np.transpose(np.array([0.5 * tout**2, tout])) expected_y = tout**2 assert_almost_equal(x, expected_x) assert_almost_equal(y, expected_y)
def getFitWaveformRLC(step): lc = 10. rc = 10. num = [1] den = [lc, rc, 1] system = signal.TransferFunction(num, den) t = np.arange(0, len(step)) tout, y, x = signal.lsim(system, step, t) return (y)
def ProcessWaveform(self, siggen_wf, outputLength, scale, switchpoint): '''Use interpolation instead of rounding''' siggen_len = self.num_steps #+ self.zeroPadding # #TODO: i don't think zero padding actually does anything anyway # if self.zeroPadding == 0: # zeroPaddingIdx = 0 # else: # siggen_wf = np.pad(siggen_wf, (self.zeroPadding,0), 'constant', constant_values=(0, 0)) # zeroPaddingIdx = self.zeroPadding #actual wf gen tout, siggen_data, x = signal.lsim(self.tfSystem, siggen_wf, self.time_steps) smax = np.amax(siggen_data) # if smax == 0: # print "waveform max is 0 -- something went wrong" # exit(0) siggen_data /= smax # siggen_data = siggen_wf[zeroPaddingIdx::] siggen_data *= scale #resample the siggen wf to the 10ns digitized data frequency w/ interpolaiton switchpoint_ceil= np.int( np.ceil(switchpoint) ) samples_to_fill = (outputLength - switchpoint_ceil) siggen_interp_fn = interpolate.interp1d(np.arange(self.num_steps ), siggen_data, kind="linear", copy="False", assume_sorted="True") siggen_start_idx = (switchpoint_ceil - switchpoint) * self.data_to_siggen_size_ratio sampled_idxs = np.arange(samples_to_fill)*self.data_to_siggen_size_ratio + siggen_start_idx out = np.zeros(outputLength) try: out[switchpoint_ceil:] = siggen_interp_fn(sampled_idxs) except ValueError: print "Something goofy happened here during interp" print outputLength print siggen_wf.size print sampled_idxs[-10:] return None return out
def getFitWaveformFoldedCascode(step): r = 1. c1 = 1. c2 = 2000. num = [c1 * r, 0] den = [c2 * r, 1] system = signal.TransferFunction(num, den) t = np.arange(0, len(step)) tout, y, x = signal.lsim(system, step, t) return (y)
def getFitWaveformOpAmp(step): r1 = 5 r2 = 5 c = 2. num = [r2] den = [r1 * r2 * c, r1] system = signal.TransferFunction(num, den) t = np.arange(0, len(step)) tout, y, x = signal.lsim(system, step, t) return (y)
def getFitWaveformFoldedCascode(step): r = 1. c1 = 1. c2 = 2000. num = [c1*r,0] den = [c2*r, 1] system = signal.TransferFunction(num, den) t = np.arange(0, len(step)) tout, y, x = signal.lsim(system, step, t) return (y)
def time_response(self, F, t, ic=None): r"""Time response for a mdof system. This method returns the time response for a mdof system given a force, time and initial conditions. Parameters ---------- F : array Force array (needs to have the same length as time array). t : array Time array. ic : array, optional The initial conditions on the state vector (zero by default). Returns ---------- t : array Time values for the output. yout : array System response. xout : array Time evolution of the state vector. Examples -------- >>> m0, m1 = 1, 1 >>> c0, c1, c2 = 1, 1, 1 >>> k0, k1, k2 = 1e3, 1e3, 1e3 >>> M = np.array([[m0, 0], ... [0, m1]]) >>> C = np.array([[c0+c1, -c2], ... [-c1, c2+c2]]) >>> K = np.array([[k0+k1, -k2], ... [-k1, k2+k2]]) >>> sys = VibeSystem(M, C, K) # create the system >>> t = np.linspace(0, 25, 1000) # time array >>> F1 = np.zeros((len(t), 2)) >>> F1[:, 1] = 1000*np.sin(40*t) # force applied on m1 >>> t, yout, xout = sys.time_response(F1, t) >>> # response on m0 >>> yout[:5, 0] array([ 0. , 0. , 0.07, 0.32, 0.61]) >>> # response on m1 >>> yout[:5, 1] array([ 0. , 0.08, 0.46, 0.79, 0.48]) """ return signal.lsim(self.lti, F, t, X0=ic)
def getFitWaveformOpAmp(step): r1 = 5 r2 = 5 c = 2. num = [r2] den = [r1*r2*c, r1] system = signal.TransferFunction(num, den) t = np.arange(0, len(step)) tout, y, x = signal.lsim(system, step, t) return (y)
def test_jordan_block(self): # Non-diagonalizable A matrix # x1' + x1 = x2 # x2' + x2 = u # y = x1 # Exact solution with u = 0 is y(t) = t exp(-t) A = np.mat("-1. 1.; 0. -1.") B = np.mat("0.; 1.") C = np.mat("1. 0.") system = self.lti_nowarn(A, B, C, 0.) t = np.linspace(0, 5) u = np.zeros_like(t) tout, y, x = lsim(system, u, t, X0=[0.0, 1.0]) expected_y = tout * np.exp(-tout) assert_almost_equal(y, expected_y)
def test_jordan_block(self): # Non-diagonalizable A matrix # x1' + x1 = x2 # x2' + x2 = u # y = x1 # Exact solution with u = 0 is y(t) = t exp(-t) A = np.mat("-1. 1.; 0. -1.") B = np.mat("0.; 1.") C = np.mat("1. 0.") system = self.lti_nowarn(A, B, C, 0.) t = np.linspace(0,5) u = np.zeros_like(t) tout, y, x = lsim(system, u, t, X0=[0.0, 1.0]) expected_y = tout * np.exp(-tout) assert_almost_equal(y, expected_y)
def create_initial(pop_num, pop, kd_min, kd_max, kp_min, kp_max, ki_min, ki_max, desired_x, system_force, dt, MSDnum, MSDden, times): """Creates the initial population of the genetic algorithm while making sure it adheres to force constraints""" for s in range(pop_num): flag = True while flag == True: flagged = 0 #Creating the random PID values kd_cur = round(random.uniform(kd_min, kd_max), 2) kp_cur = round(random.uniform(kp_min, kp_max), 2) ki_cur = round(random.uniform(ki_min, ki_max), 2) #Simulate for PID values GAnum = [kd_cur, kp_cur, ki_cur] # kd, kp, ki GAden = [0, 1, 0] GHs_num = signal.convolve(GAnum, MSDnum) GHs_den = signal.convolve(GAden, MSDden) #Create CLTF cltf_num = GHs_num cltf_den = GHs_den + GHs_num cltf = signal.TransferFunction(cltf_num, cltf_den) #Simulates the current system [s]. t_out, y_out, state = signal.lsim(cltf, U=desired_x, T=times) err_sig = [] for y in range(len(times)): err_sig.append(desired_x[y] - y_out[y]) for y in range(1, len(err_sig)): y_curr = [] y_curr = [err_sig[y - 1], err_sig[y]] err_int = np.trapz(y_curr, dx=dt) err_diff = (y_curr[1] - y_curr[0]) / dt #pid force = kp * e ki * i_e kd * d_e pid_force = kp_cur * err_sig[ y] + ki_cur * err_int + kd_cur * err_diff #if PID values exceeds requirements for time step, flag it. if system_force < pid_force: flagged = flagged + 1 #If system never exceeds max force then continue. if flagged == 0: flag = False #Into 2-D List. Access via pop[i][j] pop.insert(s, [kd_cur, kp_cur, ki_cur]) return pop
def crossover(a, b, system_force, desired_x, times, dt, MSDnum, MSDden): """Finding cut-points for crossover and joining the two parts of the two members of the population together. """ new_a = [] #Clearing previous cut_a = random.randint(1, len(a) - 1) #Makes sure there is always a cut new_a1 = a[0:cut_a] new_a2 = b[cut_a:len(b)] #Creates the new crossed-over list new_a = new_a1 + new_a2 #trying to keep force constraints upheld #Simulate for PID values GAnum = [new_a[0], new_a[1], new_a[2]] # kd, kp, ki GAden = [0, 1, 0] GHs_num = signal.convolve(GAnum, MSDnum) GHs_den = signal.convolve(GAden, MSDden) #Create CLTF cltf_num = GHs_num cltf_den = GHs_den + GHs_num cltf = signal.TransferFunction(cltf_num, cltf_den) #Simulates the current system [s]. t_out, y_out, state = signal.lsim(cltf, U=desired_x, T=times) err_sig = [] for y in range(len(times)): err_sig.append(desired_x[y] - y_out[y]) flagged = 0 for y in range(1, len(err_sig)): y_curr = [] y_curr = [err_sig[y - 1], err_sig[y]] err_int = np.trapz(y_curr, dx=dt) err_diff = (y_curr[1] - y_curr[0]) / dt #pid force = kp * e ki * i_e kd * d_e pid_force = new_a[1] * err_sig[y] + new_a[2] * err_int + new_a[ 0] * err_diff #if PID values exceeds requirements for time step, flag it. if system_force < pid_force: flagged = flagged + 1 #If system exceeds max force then crossover is aborted. if flagged > 0: new_a = a return new_a
def run(): # Generate 2nd order transfer function zeta = 0.2 # damping ratio f_n = 2.0 # natural frequency w_n = f_n * 2.0*np.pi num = [w_n**2] den = [1, 2.0*zeta*w_n, w_n**2] Gs = signal.TransferFunction(num, den) # Simulation parameters n_steps = 1000 t = np.linspace(0, 5, n_steps) u = np.ones(n_steps) # input signal u[int(n_steps/2):-1] = -1 # Simulate the output of the continuous-time system t, y, x = signal.lsim(Gs, U=u, T=t) dt = t[1] # Identification n = 2 # order of the denominator (a_1,...,a_n) m = 2 # order of the numerator (b_0,...,b_m) d = 1 rls = ArxRls(n, m, d) for k in range(n_steps): rls.update(u[k], y[k]) theta_hat = rls._theta_hat # Construct discrete-time TF from vector of estimated parameters num = [theta_hat.item(i) for i in range(n, n+m+1)] # b0 .. bm den = [theta_hat.item(i) for i in range(0, n)] # a1 .. an den.insert(0, 1.0) # add 1 to get [1, a1, .., an] Gz = signal.TransferFunction(num, den, dt=dt) # TODO: add delay of d # Simulate the output and compare with the true system t, y_est = signal.dlsim(Gz, u, t=t) plt.plot(t, y, t, y_est) plt.legend(["True", "Estimated"]) plt.xlabel("Time (s)") plt.ylabel("Amplitude (-)") plt.show() # design controller (kc, ki, kd) = computePidGmvc(num, den, dt, sigma=0.1, delta=0.0, lbda=0.5) print("kc = {}, ki = {}, kd = {}\n".format(kc, ki, kd)) return
def plot_prefilter(system, prefilter, u, t, name=""): print(prefilter.shape) print(u.shape) y = signal.convolve(u, prefilter, mode="same") print(y.shape) fig = go.Figure() fig.add_trace(go.Scatter(x=t, y=u, name="input")) fig.add_trace(go.Scatter(x=t, y=y, name="prefiltered")) _, y, _= signal.lsim(system, y, t) #fig = go.Figure() fig.add_trace(go.Scatter(x=t, y=y, name="output")) fig.add_trace(go.Scatter(x=t, y=y-u, name="error")) #fig.add_trace(go.Scatter(x=t, y=y-u, name="error")) fig.update_xaxes(title="Time (s)") fig.update_layout(title=name) fig.show()
def ltisys(T, U): tf = transfunc() t, yout, xout = scisig.lsim(tf, U=U, T=T) # t, s = scisig.step(tf, T=T) # t, i = scisig.impulse(tf, T) # data = (t, (yout, U, xout[:, 0], xout[:, 1])) # params = ({'label': 'response'}, # {'label': 'input'}, # {'label': 'xout[:, 0]'}, # {'label': 'xout[:, 1]'}) # smdplt.basicplot(data, params, xlabel='time, [s]', ylabel='response', # suptitle=' ', title='Spring-Mass-Damper Time Response', # xmax=np.max(T), filename='smd_response_ltisys.png') return yout
def plotter(f,t): transfer_function = sp.lti([1],[1,0,2.25]) t,h_t = sp.impulse(transfer_function,None,t) t,y,svec = sp.lsim(transfer_function, f, t) plt.subplot(3,1,1) plt.plot(t,f, 'r') plt.grid(True) plt.title("Input") plt.subplot(3,1,2) plt.plot(t, h_t, 'y') plt.grid(True) plt.title('Impulse response') plt.subplot(3,1,3) plt.plot(t,y,'b') plt.title('Output') plt.grid(True) plt.show()
def test_miso(self): # A system with two state variables, two inputs, and one output. A = np.array([[-1.0, 0.0], [0.0, -2.0]]) B = np.array([[1.0, 0.0], [0.0, 1.0]]) C = np.array([1.0, 0.0]) D = np.zeros((1, 2)) system = self.lti_nowarn(A, B, C, D) t = np.linspace(0, 5.0, 101) u = np.zeros_like(t) tout, y, x = lsim(system, u, t, X0=[1.0, 1.0]) expected_y = np.exp(-tout) expected_x0 = np.exp(-tout) expected_x1 = np.exp(-2.0 * tout) assert_almost_equal(y, expected_y) assert_almost_equal(x[:, 0], expected_x0) assert_almost_equal(x[:, 1], expected_x1)
def test_miso(self): # A system with two state variables, two inputs, and one output. A = np.array([[-1.0, 0.0], [0.0, -2.0]]) B = np.array([[1.0, 0.0], [0.0, 1.0]]) C = np.array([1.0, 0.0]) D = np.zeros((1,2)) system = self.lti_nowarn(A, B, C, D) t = np.linspace(0, 5.0, 101) u = np.zeros_like(t) tout, y, x = lsim(system, u, t, X0=[1.0, 1.0]) expected_y = np.exp(-tout) expected_x0 = np.exp(-tout) expected_x1 = np.exp(-2.0*tout) assert_almost_equal(y, expected_y) assert_almost_equal(x[:,0], expected_x0) assert_almost_equal(x[:,1], expected_x1)
def lsim(self, u, t, interp=0, returnall=False, X0=None, hmax=None): """Find the response of the TransferFunction to the input u with time vector t. Uses signal.lsim. return y the response of the system.""" try: out = signal.lsim(self, u, t, interp=interp, X0=X0) except LinAlgError: #if the system has a pure integrator, lsim won't work. #Call lsim2. out = self.lsim2(u, t, X0=X0, returnall=True, hmax=hmax) #override returnall because it is handled below if returnall:#most users will just want the system output y, #but some will need the (t, y, x) tuple that #signal.lsim returns return out else: return out[1]
def NLsysSimulate(self,R): """ R is the input vector. """ y_out = numpy.zeros(self.N) for i in numpy.arange(0,self.N): # Calculates the error signal: if (self.Malha == 'Fechada'): e = self.K * (R[i] - self.y0[0]) else: e = self.K * R[i] # Check if C(s) is defined. if (len(self.Cden) > 1): # Solve one step of the C(s) differential equation: t, yc, xout = signal.lsim((self.Cnum,self.Cden),numpy.array([self.e0,e]),numpy.array([0,self.delta_t]),self.X0) self.u = yc[1] self.X0 = xout[1] # Save the last state. else: self.u = e self.e0 = e # Solve one step of the non-linear differential equation: if (self.order == 1): y = odeint(self.NLsysODE1,self.y0[0],numpy.array([0,self.delta_t])) self.y0[0]=y[1] y_out[i] = y[0] elif (self.order == 2): y = odeint(self.NLsysODE2,self.y00,numpy.array([0,self.delta_t])) self.y00=y[1] y_out[i] = y[0][0] #self.tfinal = t[-1] #self.Rfinal = u[-1] #self.Wfinal = w[-1] return y_out
def plotWaveform(wfFig, np_data_early, wfScale, offset): plt.figure(wfFig.number) plt.clf() plt.title("Charge waveform") plt.xlabel("Sample number [10s of ns]") plt.ylabel("Raw ADC Value [Arb]") plt.plot( np_data_early ,color="red" ) siggen_wf= det.GetSiggenWaveform(10, 0, 10, energy=1) #siggen_fit = det.ProcessWaveform(siggen_fit) siggen_wf = np.pad(siggen_wf, (det.zeroPadding,0), 'constant', constant_values=(0, 0)) num = [-1.089e10, 5.863e17, 6.087e15] den = [1, 3.009e07, 3.743e14,5.21e18] system = signal.lti(num, den) t = np.arange(0, len(siggen_wf)*10E-9, 10E-9) tout, siggen_wf, x = signal.lsim(system, siggen_wf, t) # siggen_wf /= np.amax(siggen_wf) siggen_wf /= np.amax(siggen_wf) siggen_wf *= wfScale siggen_wf = siggen_wf[500::] plt.plot(np.arange(offset, len(siggen_wf)+offset), siggen_wf ,color="blue" ) # plt.axvline(x=lastFitSampleIdx, linewidth=1, color='r',linestyle=":") # plt.axvline(x=startGuess, linewidth=1, color='g',linestyle=":") plt.xlim(0, len(np_data_early)) value = raw_input(' --> Press s to skip, q to quit, any other key to continue with fit\n') if value == 'q': exit(0) if value == 's': return 0 return 1
def get_next_state(self,rtl_result): #ex. divide_num=2 and time_step = 1 # t_in = [0,0.5,1] t_in = np.linspace(self.current_time, self.current_time + self.time_step, self.divide_num + 1) if debug: print(t_in) sig_t = self.sig_h.val_t(t_in) noise_t = self.noise_h.val_t(t_in) _, out_t,__ = signal.lsim((self.filter1_b,self.filter1_a),sig_t+noise_t,t_in,self.sig_h.current_val) #late: >2s for 500step #_, out_t,__ = signal.lsim2((np.real(self.filter1_b),np.real(self.filter1_a)),sig_t+noise_t,t_in,self.sig_h.current_val,atol=1.0e-3,rtol=1.0e-3) self.dsm.get_next_state(out_t[-1]) self.sinc.get_next_state(self.dsm.out) #log data self.inmonitor.add_new_data(self.current_time+self.time_step,sig_t[-1]+noise_t[-1]) self.monitor.add_new_data(self.current_time+self.time_step,out_t[-1]) self.dsmonitor.add_new_data(self.current_time+self.time_step,self.dsm.out) self.sincmonitor.add_new_data(self.current_time+self.time_step,self.sinc.dif3) #cation! time = current_time self.rtlsincmonitor.add_new_data(self.current_time,rtl_result) #step end process self.current_time += self.time_step if debug: print("sig: "+str(sig_t[-1])+"@python") print("noise: "+str(sig_t[-1])+"@python") print("dt: "+str(self.dt)+"@python") print("filter_b: "+str(self.filter1_b)+"@python") print("return to: "+str(out_t[-1])+"@python") return self.dsm.out
def ProcessWaveform(self, siggen_wf, outputLength, scale, switchpoint): '''Use interpolation instead of rounding''' siggen_len = self.num_steps #+ self.zeroPadding # #TODO: i don't think zero padding actually does anything anyway # if self.zeroPadding == 0: # zeroPaddingIdx = 0 # else: # siggen_wf = np.pad(siggen_wf, (self.zeroPadding,0), 'constant', constant_values=(0, 0)) # zeroPaddingIdx = self.zeroPadding #actual wf gen tout, siggen_data, x = signal.lsim(self.tfSystem, siggen_wf, self.time_steps) siggen_data /= np.amax(siggen_data) # siggen_data = siggen_wf[zeroPaddingIdx::] siggen_data *= scale #resample the siggen wf to the 10ns digitized data frequency w/ interpolaiton switchpoint_ceil= np.int( np.ceil(switchpoint) ) samples_to_fill = (outputLength - switchpoint_ceil) siggen_interp_fn = interpolate.interp1d(np.arange(self.num_steps ), siggen_data, kind="linear", copy="False", assume_sorted="True") siggen_start_idx = switchpoint_ceil - switchpoint sampled_idxs = np.arange(samples_to_fill)*self.data_to_siggen_size_ratio + siggen_start_idx # print sampled_idxs out = np.zeros(outputLength) out[switchpoint_ceil:] = siggen_interp_fn(sampled_idxs) return out
# the solution of wc: 10 is an estimate in the handbook s = tf([1, 0], 1) G = funG(s) Gd = funGd(s) G2 = (200 * (0.01 * s + 1)) / ((10 * s + 1) * (0.1 * s + 1)) # simplified G K = wc / s / G2 L = G * K S = 1 / (1 + L) T = 1 - S Sd = S * Gd t = np.linspace(0, 3) u = np.ones(np.size(t)) [t, yr, x] = sc.lsim((T.numerator, T.denominator), u, t) [t, yd, x] = sc.lsim((Sd.numerator, Sd.denominator), u, t) plt.figure('Figure 2.22') plt.subplot(1, 2, 1) plt.title('Tracking response') plt.plot(t, yr) plt.plot(t, u, '--') plt.axis([0, 3, -0.2, 1.2]) plt.ylabel('y(t)') plt.xlabel('Time (s)') plt.subplot(1, 2, 2) plt.title('Disturbance response') plt.plot(t, yd) plt.plot(t, u * 0, '--')