Skip to content

Commit 884551a

Browse files
Add aircraft actuator uncertainty characterization example, implement the return of the legend in the uncertainty characterization plotting functions, and modify function names
1 parent 6f833aa commit 884551a

File tree

31 files changed

+402
-159
lines changed

31 files changed

+402
-159
lines changed
38.3 KB
Loading
61.7 KB
Loading
33.4 KB
Loading

doc/examples.rst

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,14 @@ particular, the response of the system states and actuator inputs are shown.
178178

179179
.. image:: _static/example_6/6_plot_inputs.png
180180

181-
Multi-Model Uncertainty Characterization
182-
----------------------------------------
181+
Multi-Model Uncertainty Characterization: Academic Model
182+
--------------------------------------------------------
183183

184-
In this example, an unstructured uncertainty set is characterized from a set
185-
of nominal and off-nominal frequency responses. The off-nominal models are
186-
generated from a nominal model by randomly perturbing the parameters within a
187-
known bound.
184+
In this example, an unstructured uncertainty set is characterized from a set of
185+
nominal and off-nominal frequency responses. This is an academic example as the
186+
uncertain model in this problem is arbitrarily selected for the purpose of
187+
demonstration. The off-nominal models are generated from a nominal model by
188+
randomly perturbing the parameters within a known bound.
188189

189190
.. literalinclude:: ../examples/7_uncertainty_characterization.py
190191
:language: python
@@ -240,7 +241,35 @@ set. The optimal weight frequency responses and fitted weights are shown below.
240241

241242
.. image:: _static/example_7/7_uncertainty_weight.png
242243

244+
Multi-Model Uncertainty Characterization: Aircraft Actuator Model
245+
-----------------------------------------------------------------
243246

247+
In this example, an unstructured uncertainty set is characterized from a set of
248+
nominal and off-nominal frequency responses. In this example, the uncertainty
249+
of an aircraft actuator model is characterized using an actuator model from an
250+
example given in Section 14.1 of [M04]_.
251+
252+
.. literalinclude:: ../examples/8_aircraft_actuator_uncertainty_characterization.py
253+
:language: python
254+
255+
The off-nominal frequency response data is generated by sampling valid
256+
perturbations from the uncertainty model provided in the problem statement.
257+
258+
.. image:: _static/example_8/8_sval_actuator.png
259+
260+
Three different candidate uncertainty models are evaluated: additive
261+
uncertainty, multiplicative input uncertainty, and inverse multiplicative
262+
input uncertainty. The multiplicative input uncertainty is selected as it
263+
yields the smallest residual singular values.
264+
265+
.. image:: _static/example_8/8_sval_residual_max.png
266+
267+
The left uncertainty weight is constrained to be scalar whereas the right uncertainty
268+
weight is constrained to the identity matrix. Given that the right uncertainty
269+
weight is the identity matrix, a fit does not need to be performed for this weight
270+
as it will be neglected in the generalized plant.
271+
272+
.. image:: _static/example_8/8_magnitude_uncertainty_weight.png
244273

245274

246275

examples/6_dk_iteration_non_square_perturbation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def example_dk_iter_list_order_aircraft():
5757
# DK-iteration controller synthesis
5858
dk_iter = dkpy.DkIterListOrder(
5959
controller_synthesis=dkpy.HinfSynLmi(
60-
lmi_strictness=5e-7, # Have to play with tolerances.
60+
lmi_strictness=5e-7,
6161
solver_params=dict(
6262
solver="MOSEK",
6363
eps=5e-8,
@@ -74,7 +74,7 @@ def example_dk_iter_list_order_aircraft():
7474
),
7575
),
7676
d_scale_fit=dkpy.DScaleFitSlicot(),
77-
fit_orders=[4, 4],
77+
fit_orders=[4, 4, 4],
7878
)
7979
# Alternative MATLAB block structure description
8080
# block_structure = np.array([[n_u_delta, n_y_delta], [n_w, n_z]])

examples/7_uncertainty_characterization.py

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,12 @@
88
def example_uncertainty_characterization():
99
"""Multi-model uncertainty characterization from frequency response data."""
1010

11-
# Generate example data
11+
# Load example data
1212
eg = dkpy.example_multimodel_uncertainty()
1313
response_nom = eg["complex_response_nominal"]
1414
response_offnom_list = eg["complex_response_offnominal_list"]
1515
omega = eg["omega"]
1616

17-
# Plot: Magnitude response of nominal and off-nominal systems
18-
fig, _ = dkpy.plot_magnitude_response_uncertain_model_set(
19-
response_nom,
20-
response_offnom_list,
21-
omega,
22-
)
23-
24-
# Plot: Phase response of nominal and off-nominal systems
25-
fig, _ = dkpy.plot_phase_response_uncertain_model_set(
26-
response_nom,
27-
response_offnom_list,
28-
omega,
29-
)
30-
31-
# Plot: Singular value response of nominal and off-nominal systems
32-
fig, ax = dkpy.plot_singular_value_response_uncertain_model_set(
33-
response_nom,
34-
response_offnom_list,
35-
omega,
36-
)
37-
3817
# Uncertainty models
3918
uncertainty_models = {
4019
"additive",
@@ -44,41 +23,58 @@ def example_uncertainty_characterization():
4423
"inverse_multiplicative_input",
4524
"inverse_multiplicative_output",
4625
}
26+
27+
# Compute uncertainty residual frequency response
4728
response_residuals_dict = dkpy.compute_uncertainty_residual_response(
4829
response_nom,
4930
response_offnom_list,
5031
uncertainty_models,
5132
)
5233

53-
# Plot: Singular value response of uncerainty residuals
54-
figure_dict = dkpy.plot_singular_value_response_residual(
55-
response_residuals_dict, omega
56-
)
57-
58-
# Plot: Comparison of singular value response of uncerainty residuals for each
59-
# uncertainty model
60-
fig, _ = dkpy.plot_singular_value_response_residual_comparison(
61-
response_residuals_dict, omega
62-
)
63-
6434
# Compute uncertainty weight frequency response
6535
response_weight_left, response_weight_right = (
66-
dkpy.compute_optimal_uncertainty_weight_response(
36+
dkpy.compute_uncertainty_weight_response(
6737
response_residuals_dict["inverse_additive"], "diagonal", "diagonal"
6838
)
6939
)
7040

7141
# Fit overbounding stable and minimum-phase uncertainty weight system
72-
weight_left = dkpy.fit_overbounding_uncertainty_weight(
73-
response_weight_left, omega, [4, 5]
42+
weight_left = dkpy.fit_uncertainty_weight(response_weight_left, omega, [4, 5])
43+
weight_right = dkpy.fit_uncertainty_weight(response_weight_right, omega, [3, 5])
44+
45+
# Plot: Magnitude response of nominal and off-nominal systems
46+
dkpy.plot_magnitude_response_uncertain_model_set(
47+
response_nom,
48+
response_offnom_list,
49+
omega,
50+
)
51+
52+
# Plot: Phase response of nominal and off-nominal systems
53+
dkpy.plot_phase_response_uncertain_model_set(
54+
response_nom,
55+
response_offnom_list,
56+
omega,
7457
)
75-
weight_right = dkpy.fit_overbounding_uncertainty_weight(
76-
response_weight_right, omega, [3, 5]
58+
59+
# Plot: Singular value response of nominal and off-nominal systems
60+
dkpy.plot_singular_value_response_uncertain_model_set(
61+
response_nom,
62+
response_offnom_list,
63+
omega,
64+
)
65+
66+
# Plot: Singular value response of uncerainty residuals
67+
dkpy.plot_singular_value_response_residual(response_residuals_dict, omega)
68+
69+
# Plot: Comparison of singular value response of uncerainty residuals for each
70+
# uncertainty model
71+
dkpy.plot_singular_value_response_residual_comparison(
72+
response_residuals_dict, omega
7773
)
7874

7975
# Plot: Magnitude response of uncertainty weight frequency response and overbounding
8076
# fit
81-
fig, _ = dkpy.plot_magnitude_response_uncertainty_weight(
77+
dkpy.plot_magnitude_response_uncertainty_weight(
8278
response_weight_left,
8379
response_weight_right,
8480
omega,
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""Multi-model aircraft actuator uncertainty characterization from frequency response
2+
data.
3+
"""
4+
5+
from matplotlib import pyplot as plt
6+
7+
import dkpy
8+
9+
10+
def example_aircraft_uncertainty_characterization():
11+
"""Multi-model aircraft actuator uncertainty characterization from frequency
12+
response data.
13+
"""
14+
# Load example data
15+
eg = dkpy.example_aircraft_actuator_uncertainty()
16+
response_actuator = eg["response_actuator_nominal"]
17+
response_actuator_offnom_list = eg["response_actuator_offnominal"]
18+
omega = eg["omega"]
19+
20+
# Compute the residual response for different uncertainty models
21+
complex_response_residual_dict = dkpy.compute_uncertainty_residual_response(
22+
response_actuator,
23+
response_actuator_offnom_list,
24+
{"additive", "multiplicative_input", "inverse_multiplicative_input"},
25+
)
26+
27+
# Compute the optimal uncertainty weights with a given structure
28+
response_weight_left, response_weight_right = (
29+
dkpy.compute_uncertainty_weight_response(
30+
complex_response_residual_dict["multiplicative_input"],
31+
"scalar",
32+
"identity",
33+
)
34+
)
35+
36+
# Fit an overbounding LTI system to the optimal uncertainty weight response
37+
weight_left = dkpy.fit_uncertainty_weight(response_weight_left, omega, 1)
38+
39+
# Plot: Singular value response of nominal and off-nominal systems
40+
fig, _, _ = dkpy.plot_singular_value_response_uncertain_model_set(
41+
response_actuator, response_actuator_offnom_list, omega, hz=True
42+
)
43+
fig.savefig("singular_value_plot.png")
44+
45+
# Plot: Comparison of singular value response of uncerainty residuals for each
46+
# uncertainty model
47+
fig, _, _ = dkpy.plot_singular_value_response_residual_comparison(
48+
complex_response_residual_dict, omega, hz=True
49+
)
50+
fig.savefig("residual_comparison.png")
51+
52+
# Plot: Magnitude response of uncertainty weight frequency response and overbounding
53+
# fit
54+
fig, _, _ = dkpy.plot_magnitude_response_uncertainty_weight(
55+
response_weight_left,
56+
response_weight_right,
57+
omega,
58+
weight_left=weight_left,
59+
hz=True,
60+
)
61+
fig.savefig("weight.png")
62+
plt.show()
63+
64+
65+
if __name__ == "__main__":
66+
example_aircraft_uncertainty_characterization()

0 commit comments

Comments
 (0)