-
Notifications
You must be signed in to change notification settings - Fork 446
Description
Hey,
I'm currently running version 0.9.2 and face some issues with the frequency_response() function with rather complex TransferFunctions. In my minimal working example, I create a MIMO system from state-space matrices with 24 in- and 18 outputs. In the next step, I extracted two transfer functions (H&P) and performed a simple calculation with both to create a new TF (Hcl). Using frequency_response() function on both the original TFs I get the expected result. For the new TF Hcl however, the response looks very messy in magnitude as well as in phase.
To get a short time fix, I took the frequency response of the original functions, converted magnitude and phase into a complex number and redid the calculation, which returned a the expected form of Hcl, as seen in the plot below.
The code i used is the following:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import control
# Importing State-Space matrices and check if dimensions are correct
ssAspoiler = np.loadtxt(open('ssA_spoiler.csv', 'rb'), delimiter=',')
ssB = np.loadtxt(open('ssB.csv', 'rb'), delimiter=',')
ssC = np.loadtxt(open('ssC.csv', 'rb'), delimiter=',')
ssD = np.loadtxt(open('ssD.csv', 'rb'), delimiter=',')
print('dim(A) =', np.shape(ssAspoiler))
print('dim(B) =', np.shape(ssB))
print('dim(C) =', np.shape(ssC))
print('dim(D) =', np.shape(ssD))
# Define Frequency Array
Frequency_Array = np.linspace(0.1, 100, int(1e5))
Omega_Array = Frequency_Array * (2*np.pi)
# Create State-Space System
sys = control.StateSpace(ssAspoiler, ssB, ssC, ssD)
TF = control.ss2tf(sys)
# Choose in- and outputs
i1 = 0
i2 = 6
o = 12
# Extract TFs from State-Space System
H = control.TransferFunction(TF.num[o][i1], TF.den[o][i1])
P = control.TransferFunction(TF.num[o][i2], TF.den[o][i2])
# Calculating (closed loop) TF from existing TF's
Hcl = H / (1 + P)
# Compute frequency_response() of all TF from above
mag_H, phase_H, _ = control.frequency_response(H, Omega_Array)
mag_P, phase_P, _ = control.frequency_response(P, Omega_Array)
mag_Hcl, phase_Hcl, _ = control.frequency_response(Hcl, Omega_Array)
# Try different way to get proper frequency response of Hcl
P_comp = mag_P * np.exp(1j*phase_P)
H_comp = mag_H * np.exp(1j*phase_H)
Hcl_comp = (H_comp) / (1 + P_comp)
# Plot frequency responses
plt.figure(dpi = 150, figsize = (10, 6))
plt.loglog(Frequency_Array, mag_Hcl, color = 'k', label = 'Hcl from frequency_reponse()')
plt.loglog(Frequency_Array, np.abs(Hcl_comp), linewidth = .75, color = 'r', label = 'Hcl from complex calcs')
plt.loglog(Frequency_Array, mag_H, label = 'H', linewidth = .75)
plt.loglog(Frequency_Array, mag_P, label = 'P', linewidth = .75)
plt.grid(True, which = 'both')
plt.xlabel('Frequency [Hz]')
plt.ylabel('Magnitude')
plt.legend(loc = 'lower left')
plt.show()
Since I want to use control.feedback() later on as well, this problem is especially problematic, since it also appears there.
Unfortunately, I can't pinpoint where this problem originates from, so I am hoping you might understand the reasons behind that. For completeness, I also attached the .txt files with the state-space matrices.
EDIT: I should mention, that I don't see this kind of behaviour for simple transfer functions.
