|
19 | 19 | from control.dtime import sample_system
|
20 | 20 | from control.lti import evalfr
|
21 | 21 | from control.statesp import StateSpace, _convert_to_statespace, tf2ss, \
|
22 |
| - _statesp_defaults, _rss_generate |
| 22 | + _statesp_defaults, _rss_generate, linfnorm |
23 | 23 | from control.iosys import ss, rss, drss
|
24 | 24 | from control.tests.conftest import ismatarrayout, slycotonly
|
25 | 25 | from control.xferfcn import TransferFunction, ss2tf
|
26 | 26 |
|
| 27 | + |
27 | 28 | from .conftest import editsdefaults
|
28 | 29 |
|
| 30 | + |
29 | 31 | class TestStateSpace:
|
30 | 32 | """Tests for the StateSpace class."""
|
31 | 33 |
|
@@ -1107,3 +1109,52 @@ def test_latex_repr_testsize(editsdefaults):
|
1107 | 1109 |
|
1108 | 1110 | gstatic = ss([], [], [], 1)
|
1109 | 1111 | assert gstatic._repr_latex_() is None
|
| 1112 | + |
| 1113 | + |
| 1114 | +class TestLinfnorm: |
| 1115 | + # these are simple tests; we assume ab13dd is correct |
| 1116 | + # python-control specific behaviour is: |
| 1117 | + # - checking for continuous- and discrete-time |
| 1118 | + # - scaling fpeak for discrete-time |
| 1119 | + # - handling static gains |
| 1120 | + |
| 1121 | + # the underdamped gpeak and fpeak are found from |
| 1122 | + # gpeak = 1/(2*zeta*(1-zeta**2)**0.5) |
| 1123 | + # fpeak = wn*(1-2*zeta**2)**0.5 |
| 1124 | + @pytest.fixture(params=[ |
| 1125 | + ('static', ct.tf, ([1.23],[1]), 1.23, 0), |
| 1126 | + ('underdamped', ct.tf, ([100],[1, 2*0.5*10, 100]), 1.1547005, 7.0710678), |
| 1127 | + ]) |
| 1128 | + def ct_siso(self, request): |
| 1129 | + name, systype, sysargs, refgpeak, reffpeak = request.param |
| 1130 | + return systype(*sysargs), refgpeak, reffpeak |
| 1131 | + |
| 1132 | + @pytest.fixture(params=[ |
| 1133 | + ('underdamped', ct.tf, ([100],[1, 2*0.5*10, 100]), 1e-4, 1.1547005, 7.0710678), |
| 1134 | + ]) |
| 1135 | + def dt_siso(self, request): |
| 1136 | + name, systype, sysargs, dt, refgpeak, reffpeak = request.param |
| 1137 | + return ct.c2d(systype(*sysargs), dt), refgpeak, reffpeak |
| 1138 | + |
| 1139 | + @slycotonly |
| 1140 | + def test_linfnorm_ct_siso(self, ct_siso): |
| 1141 | + sys, refgpeak, reffpeak = ct_siso |
| 1142 | + gpeak, fpeak = linfnorm(sys) |
| 1143 | + np.testing.assert_allclose(gpeak, refgpeak) |
| 1144 | + np.testing.assert_allclose(fpeak, reffpeak) |
| 1145 | + |
| 1146 | + @slycotonly |
| 1147 | + def test_linfnorm_dt_siso(self, dt_siso): |
| 1148 | + sys, refgpeak, reffpeak = dt_siso |
| 1149 | + gpeak, fpeak = linfnorm(sys) |
| 1150 | + # c2d pole-mapping has round-off |
| 1151 | + np.testing.assert_allclose(gpeak, refgpeak) |
| 1152 | + np.testing.assert_allclose(fpeak, reffpeak) |
| 1153 | + |
| 1154 | + @slycotonly |
| 1155 | + def test_linfnorm_ct_mimo(self, ct_siso): |
| 1156 | + siso, refgpeak, reffpeak = ct_siso |
| 1157 | + sys = ct.append(siso, siso) |
| 1158 | + gpeak, fpeak = linfnorm(sys) |
| 1159 | + np.testing.assert_allclose(gpeak, refgpeak) |
| 1160 | + np.testing.assert_allclose(fpeak, reffpeak) |
0 commit comments