Skip to content

Commit eb4cb77

Browse files
Refactor SISO uncertainty weight fit
1 parent 0b8bfda commit eb4cb77

File tree

6 files changed

+807
-416
lines changed

6 files changed

+807
-416
lines changed

example.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import numpy as np
2+
import control
3+
import slycot
4+
from matplotlib import pyplot as plt
5+
6+
import dkpy
7+
8+
# Frequency range
9+
omega_min = 0.1
10+
omega_max = 10
11+
num_omega = 100
12+
omega = np.logspace(np.log10(omega_min), np.log10(omega_max), num_omega)
13+
14+
# Ground-truth system
15+
sys = control.tf([1, 2, 2], [1, 2.5, 1.5]) * control.tf(1, [1, 0.1])
16+
sys = sys * control.tf([1, 3.75, 3.5], [1, 2.5, 13])
17+
18+
damping_ratio_1 = 0.01
19+
freq_nat_1 = 200
20+
damping_ratio_2 = 0.1
21+
freq_nat_2 = 500
22+
23+
# sys = control.tf(
24+
# [1 / freq_nat_1**2, 2 * damping_ratio_1 / freq_nat_1, 1],
25+
# [1 / freq_nat_2**2, 2 * damping_ratio_2 / freq_nat_2, 1],
26+
# )
27+
28+
# System frequency response
29+
frd_sys = sys.frequency_response(omega)
30+
fresp_sys = frd_sys.response
31+
mag_sys = frd_sys.magnitude
32+
# mag_sys = mag_sys * (1 + np.random.normal(0.0, 0.05, mag_sys.size))
33+
34+
# Magnitude scaling
35+
max_mag_sys = np.max(mag_sys)
36+
min_mag_sys = np.min(mag_sys)
37+
# scale_mag_sys = np.sqrt(max_mag_sys * min_mag_sys)
38+
# mag_sys_nrml = mag_sys / scale_mag_sys
39+
40+
#
41+
order = 5
42+
mosek_params = {
43+
"MSK_DPAR_INTPNT_TOL_PFEAS": 1e-12,
44+
"MSK_DPAR_INTPNT_TOL_DFEAS": 1e-12,
45+
"MSK_DPAR_INTPNT_TOL_REL_GAP": 1e-12,
46+
"MSK_DPAR_INTPNT_TOL_INFEAS": 1e-12,
47+
}
48+
linear_solver_param = {
49+
"solver": "MOSEK",
50+
"verbose": False,
51+
"mosek_params": mosek_params,
52+
"warm_start": True,
53+
}
54+
55+
56+
alpha = np.sqrt(omega[0] * omega[-1])
57+
theta = 2 * np.atan(omega / alpha)
58+
59+
weight = dkpy.fit_magnitude_siso_ct(omega, mag_sys, 4)
60+
61+
62+
n, A, B, C, D = slycot.sb10yd(
63+
discfl=0, # Continuous-time
64+
flag=1, # Constrain stable, minimum phase
65+
lendat=omega.shape[0],
66+
rfrdat=np.real(fresp_sys),
67+
ifrdat=np.imag(fresp_sys),
68+
omega=omega,
69+
n=order,
70+
tol=0, # Length of cache array
71+
)
72+
weight_slycot = control.StateSpace(A, B, C, D, dt=0)
73+
74+
# Estimated Frequency response
75+
omega_fit = np.logspace(np.log10(omega_min), np.log10(omega_max), 100)
76+
frd_fit = weight.frequency_response(omega_fit)
77+
mag_fit = frd_fit.magnitude
78+
frd_fit_slycot = weight_slycot.frequency_response(omega_fit)
79+
mag_fit_slycot = frd_fit_slycot.magnitude
80+
81+
# Plot: Preview log-magnitude response
82+
fig, ax = plt.subplots(layout="constrained")
83+
ax.semilogx(omega, control.mag2db(mag_sys), "--*", label="Magnitude Data")
84+
ax.semilogx(omega_fit, control.mag2db(mag_fit), label=f"Fit Magnitude (Order {order})")
85+
ax.semilogx(
86+
omega_fit,
87+
control.mag2db(mag_fit_slycot),
88+
label=f"Slycot Fit Magnitude (Order {order})",
89+
)
90+
ax.set_ylabel("Magnitude (dB)")
91+
ax.set_xlabel("$f$ (Hz)")
92+
ax.legend()
93+
# fig.savefig(f"figs/log_cheby_fit_order_{order}.pdf")
94+
plt.show()
95+
96+
# Plot: Preview magnitude response
97+
fig, ax = plt.subplots(layout="constrained")
98+
ax.semilogx(omega, mag_sys, "--*", label="Magnitude Data")
99+
ax.semilogx(omega_fit, mag_fit, label=f"Fit Magnitude (Order {order})")
100+
ax.set_ylabel("Magnitude (-)")
101+
ax.set_xlabel("$f$ (Hz)")
102+
ax.legend()
103+
# fig.savefig(f"figs/log_cheby_fit_order_{order}.pdf")
104+
plt.show()
105+
106+
# Plot: Preview residual response
107+
fig, ax = plt.subplots(layout="constrained")
108+
ax.semilogx(omega, mag_sys**2 / mag_fit**2 - 1, "--*", label="Magnitude Data")
109+
ax.semilogx(
110+
omega, mag_sys**2 / mag_fit_slycot**2 - 1, "--*", label=" Slycot Magnitude Data"
111+
)
112+
ax.set_ylabel("Residual (-)")
113+
ax.set_xlabel("$f$ (Hz)")
114+
ax.legend()
115+
# fig.savefig(f"figs/log_cheby_fit_order_{order}.pdf")
116+
plt.show()

src/dkpy/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .controller_synthesis import *
44
from .dk_iteration import *
55
from .d_scale_fit import *
6+
from .lti_system_fit import *
67
from .structured_singular_value import *
78
from .uncertainty_structure import *
89
from .uncertainty_characterization import *

0 commit comments

Comments
 (0)