Closed
Description
StateSpace.freqresp current converts to a transfer-function matrix (TFM) to evaluate the frequency response (see [1]) .
Polynomials can give numerical problems (see below), so this method should probably use [2]
(unfortunately not currently exposed in Slycot). This technique uses an orthogonal similarity transform to make the system quicker to evaluate.
One possible problem is that if one evaluates a decoupled (diagonal TFM) system in which one system has poles on the imaginary axis, I imagine the whole frequency response will be infinite. I'm not sure if this is really important.
[1]
python-control/control/statesp.py
Line 398 in cdd3e73
[2] http://slicot.org/objects/software/shared/doc/TB05AD.html
A script to demonstrate the problem:
import numpy as np
import control
wn = 1;
zeta = 0.01;
g = control.tf(wn**2, [1,2*zeta*wn,wn**2])
def trivial_evalfr(gss,w):
I = np.eye(*gss.A.shape)
return np.dot(gss.C,np.linalg.solve(1j*w*I-gss.A,gss.B)) + gss.D
def trivpow(g,n):
from functools import reduce
from operator import mul
assert g.inputs == g.outputs
I = np.eye(g.inputs)
return reduce(mul,[g for i in range(n)])
gss = control.ss(g)
print()
print('{:3s} {:>9s} {:>9s} {:>9s} {:>9s}'.format('exp','tfv/ref','tfv/ref','ssv/ref','ssv/ref'))
print('{:3s} {:>9s} {:>9s} {:>9s} {:>9s}'.format('','1','dB','1','dB'))
exps = range(1,21)
gtfs = [trivpow(g,i)
for i in exps]
gsss = [trivpow(gss,i)
for i in exps]
for exp,gtfi,gssi in zip(exps,gtfs,gsss):
ref = g.evalfr(1)**exp
tfv = gtfi.evalfr(1)
ssv = trivial_evalfr(gssi,1)
tferr = np.abs(tfv/ref)[0,0]
sserr = np.abs(ssv/ref)[0,0]
db = lambda x: 20*np.log10(x)
print('{:3d} {:9.2e} {:9.2e} {:9.2e} {:9.2e}'.format(exp,tferr,db(tferr),sserr,db(sserr)))
result is
exp tfv/ref tfv/ref ssv/ref ssv/ref
1 dB 1 dB
1 1.00e+00 0.00e+00 1.00e+00 -6.75e-15
2 1.00e+00 9.57e-13 1.00e+00 -1.54e-14
3 1.00e+00 -8.69e-12 1.00e+00 -2.41e-14
4 1.00e+00 -4.36e-08 1.00e+00 -3.18e-14
5 1.00e+00 1.10e-07 1.00e+00 -3.95e-14
6 1.00e+00 7.16e-05 1.00e+00 -4.82e-14
7 1.00e+00 1.65e-03 1.00e+00 -5.40e-14
8 9.01e-01 -9.08e-01 1.00e+00 -6.27e-14
9 2.88e-02 -3.08e+01 1.00e+00 -7.04e-14
10 2.51e-04 -7.20e+01 1.00e+00 -8.00e-14
11 2.27e-05 -9.29e+01 1.00e+00 -8.68e-14
12 7.62e-08 -1.42e+02 1.00e+00 -9.35e-14
13 6.38e-10 -1.84e+02 1.00e+00 -1.03e-13
14 1.38e-11 -2.17e+02 1.00e+00 -1.09e-13
15 4.16e-13 -2.48e+02 1.00e+00 -1.20e-13
16 1.76e-15 -2.95e+02 1.00e+00 -1.25e-13
17 1.13e-17 -3.39e+02 1.00e+00 -1.33e-13
18 2.74e-20 -3.91e+02 1.00e+00 -1.41e-13
19 6.49e-22 -4.24e+02 1.00e+00 -1.49e-13
20 1.72e-24 -4.75e+02 1.00e+00 -1.56e-13