Skip to content

Commit e10b798

Browse files
author
Henrik Sandberg
committed
* In sysnorm: Warnings now of type UserWarning
* In sysnorm_test: Use pytest.warns context manager
1 parent a95daaf commit e10b798

File tree

2 files changed

+41
-30
lines changed

2 files changed

+41
-30
lines changed

control/sysnorm.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def _h2norm_slycot(sys, print_warning=True):
5555
if dico == 'C':
5656
if any(D.flat != 0):
5757
if print_warning:
58-
warnings.warn("System has a direct feedthrough term!")
58+
warnings.warn("System has a direct feedthrough term!", UserWarning)
5959
return float("inf")
6060
else:
6161
return 0.0
@@ -67,15 +67,15 @@ def _h2norm_slycot(sys, print_warning=True):
6767
except SlycotArithmeticError as e:
6868
if e.info == 3:
6969
if print_warning:
70-
warnings.warn("System has pole(s) on the stability boundary!")
70+
warnings.warn("System has pole(s) on the stability boundary!", UserWarning)
7171
return float("inf")
7272
elif e.info == 5:
7373
if print_warning:
74-
warnings.warn("System has a direct feedthrough term!")
74+
warnings.warn("System has a direct feedthrough term!", UserWarning)
7575
return float("inf")
7676
elif e.info == 6:
7777
if print_warning:
78-
warnings.warn("System is unstable!")
78+
warnings.warn("System is unstable!", UserWarning)
7979
return float("inf")
8080
else:
8181
raise e
@@ -91,7 +91,7 @@ def norm(system, p=2, tol=1e-10, print_warning=True, method=None):
9191
system : LTI (:class:`StateSpace` or :class:`TransferFunction`)
9292
System in continuous or discrete time for which the norm should be computed.
9393
p : int or str
94-
Type of norm to be computed. p=2 gives the H2 norm, and p='inf' gives the L-infinity norm.
94+
Type of norm to be computed. ``p=2`` gives the H2 norm, and ``p='inf'`` gives the L-infinity norm.
9595
tol : float
9696
Relative tolerance for accuracy of L-infinity norm computation. Ignored
9797
unless p='inf'.
@@ -145,15 +145,15 @@ def norm(system, p=2, tol=1e-10, print_warning=True, method=None):
145145
poles_real_part = G.poles().real
146146
if any(np.isclose(poles_real_part, 0.0)): # Poles on imaginary axis
147147
if print_warning:
148-
warnings.warn("Poles close to, or on, the imaginary axis. Norm value may be uncertain.")
148+
warnings.warn("Poles close to, or on, the imaginary axis. Norm value may be uncertain.", UserWarning)
149149
return float('inf')
150150
elif any(poles_real_part > 0.0): # System unstable
151151
if print_warning:
152-
warnings.warn("System is unstable!")
152+
warnings.warn("System is unstable!", UserWarning)
153153
return float('inf')
154154
elif any(D.flat != 0): # System has direct feedthrough
155155
if print_warning:
156-
warnings.warn("System has a direct feedthrough term!")
156+
warnings.warn("System has a direct feedthrough term!", UserWarning)
157157
return float('inf')
158158

159159
else:
@@ -169,7 +169,7 @@ def norm(system, p=2, tol=1e-10, print_warning=True, method=None):
169169
# Test next is a precaution in case the Lyapunov equation is ill conditioned.
170170
if any(la.eigvals(P).real < 0.0):
171171
if print_warning:
172-
warnings.warn("There appears to be poles close to the imaginary axis. Norm value may be uncertain.")
172+
warnings.warn("There appears to be poles close to the imaginary axis. Norm value may be uncertain.", UserWarning)
173173
return float('inf')
174174
else:
175175
norm_value = np.sqrt(np.trace(C@P@C.T)) # Argument in sqrt should be non-negative
@@ -187,11 +187,11 @@ def norm(system, p=2, tol=1e-10, print_warning=True, method=None):
187187
poles_abs = abs(G.poles())
188188
if any(np.isclose(poles_abs, 1.0)): # Poles on imaginary axis
189189
if print_warning:
190-
warnings.warn("Poles close to, or on, the complex unit circle. Norm value may be uncertain.")
190+
warnings.warn("Poles close to, or on, the complex unit circle. Norm value may be uncertain.", UserWarning)
191191
return float('inf')
192192
elif any(poles_abs > 1.0): # System unstable
193193
if print_warning:
194-
warnings.warn("System is unstable!")
194+
warnings.warn("System is unstable!", UserWarning)
195195
return float('inf')
196196

197197
else:
@@ -207,7 +207,7 @@ def norm(system, p=2, tol=1e-10, print_warning=True, method=None):
207207
# Test next is a precaution in case the Lyapunov equation is ill conditioned.
208208
if any(la.eigvals(P).real < 0.0):
209209
if print_warning:
210-
warnings.warn("Warning: There appears to be poles close to the complex unit circle. Norm value may be uncertain.")
210+
warnings.warn("Warning: There appears to be poles close to the complex unit circle. Norm value may be uncertain.", UserWarning)
211211
return float('inf')
212212
else:
213213
norm_value = np.sqrt(np.trace(C@P@C.T + D@D.T)) # Argument in sqrt should be non-negative
@@ -226,12 +226,12 @@ def norm(system, p=2, tol=1e-10, print_warning=True, method=None):
226226
if G.isdtime(): # Discrete time
227227
if any(np.isclose(abs(poles), 1.0)): # Poles on unit circle
228228
if print_warning:
229-
warnings.warn("Poles close to, or on, the complex unit circle. Norm value may be uncertain.")
229+
warnings.warn("Poles close to, or on, the complex unit circle. Norm value may be uncertain.", UserWarning)
230230
return float('inf')
231231
else: # Continuous time
232232
if any(np.isclose(poles.real, 0.0)): # Poles on imaginary axis
233233
if print_warning:
234-
warnings.warn("Poles close to, or on, the imaginary axis. Norm value may be uncertain.")
234+
warnings.warn("Poles close to, or on, the imaginary axis. Norm value may be uncertain.", UserWarning)
235235
return float('inf')
236236

237237
# Use slycot, if available, to compute (finite) norm

control/tests/sysnorm_test.py

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,51 @@
88

99
import control as ct
1010
import numpy as np
11+
import pytest
12+
1113

1214
def test_norm_1st_order_stable_system():
1315
"""First-order stable continuous-time system"""
1416
s = ct.tf('s')
17+
1518
G1 = 1/(s+1)
16-
assert np.allclose(ct.norm(G1, p='inf', tol=1e-9, print_warning=False), 1.0) # Comparison to norm computed in MATLAB
17-
assert np.allclose(ct.norm(G1, p=2, print_warning=False), 0.707106781186547) # Comparison to norm computed in MATLAB
19+
assert np.allclose(ct.norm(G1, p='inf', tol=1e-9 ), 1.0) # Comparison to norm computed in MATLAB
20+
assert np.allclose(ct.norm(G1, p=2), 0.707106781186547) # Comparison to norm computed in MATLAB
1821

1922
Gd1 = ct.sample_system(G1, 0.1)
20-
assert np.allclose(ct.norm(Gd1, p='inf', tol=1e-9, print_warning=False), 1.0) # Comparison to norm computed in MATLAB
21-
assert np.allclose(ct.norm(Gd1, p=2, print_warning=False), 0.223513699524858) # Comparison to norm computed in MATLAB
23+
assert np.allclose(ct.norm(Gd1, p='inf', tol=1e-9), 1.0) # Comparison to norm computed in MATLAB
24+
assert np.allclose(ct.norm(Gd1, p=2), 0.223513699524858) # Comparison to norm computed in MATLAB
2225

2326

2427
def test_norm_1st_order_unstable_system():
2528
"""First-order unstable continuous-time system"""
2629
s = ct.tf('s')
30+
2731
G2 = 1/(1-s)
28-
assert np.allclose(ct.norm(G2, p='inf', tol=1e-9, print_warning=False), 1.0) # Comparison to norm computed in MATLAB
29-
assert ct.norm(G2, p=2, print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
32+
assert np.allclose(ct.norm(G2, p='inf', tol=1e-9), 1.0) # Comparison to norm computed in MATLAB
33+
with pytest.warns(UserWarning, match="System is unstable!"):
34+
assert ct.norm(G2, p=2) == float('inf') # Comparison to norm computed in MATLAB
3035

3136
Gd2 = ct.sample_system(G2, 0.1)
32-
assert np.allclose(ct.norm(Gd2, p='inf', tol=1e-9, print_warning=False), 1.0) # Comparison to norm computed in MATLAB
33-
assert ct.norm(Gd2, p=2, print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
37+
assert np.allclose(ct.norm(Gd2, p='inf', tol=1e-9), 1.0) # Comparison to norm computed in MATLAB
38+
with pytest.warns(UserWarning, match="System is unstable!"):
39+
assert ct.norm(Gd2, p=2) == float('inf') # Comparison to norm computed in MATLAB
3440

3541
def test_norm_2nd_order_system_imag_poles():
3642
"""Second-order continuous-time system with poles on imaginary axis"""
3743
s = ct.tf('s')
44+
3845
G3 = 1/(s**2+1)
39-
assert ct.norm(G3, p='inf', print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
40-
assert ct.norm(G3, p=2, print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
46+
with pytest.warns(UserWarning, match="Poles close to, or on, the imaginary axis."):
47+
assert ct.norm(G3, p='inf') == float('inf') # Comparison to norm computed in MATLAB
48+
with pytest.warns(UserWarning, match="Poles close to, or on, the imaginary axis."):
49+
assert ct.norm(G3, p=2) == float('inf') # Comparison to norm computed in MATLAB
4150

4251
Gd3 = ct.sample_system(G3, 0.1)
43-
assert ct.norm(Gd3, p='inf', print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
44-
assert ct.norm(Gd3, p=2, print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
52+
with pytest.warns(UserWarning, match="Poles close to, or on, the complex unit circle."):
53+
assert ct.norm(Gd3, p='inf') == float('inf') # Comparison to norm computed in MATLAB
54+
with pytest.warns(UserWarning, match="Poles close to, or on, the complex unit circle."):
55+
assert ct.norm(Gd3, p=2) == float('inf') # Comparison to norm computed in MATLAB
4556

4657
def test_norm_3rd_order_mimo_system():
4758
"""Third-order stable MIMO continuous-time system"""
@@ -55,9 +66,9 @@ def test_norm_3rd_order_mimo_system():
5566
[-0.863652821988714, -1.214117043615409, -0.006849328103348]])
5667
D = np.zeros((2,2))
5768
G4 = ct.ss(A,B,C,D) # Random system generated in MATLAB
58-
assert np.allclose(ct.norm(G4, p='inf', tol=1e-9, print_warning=False), 4.276759162964244) # Comparison to norm computed in MATLAB
59-
assert np.allclose(ct.norm(G4, p=2, print_warning=False), 2.237461821810309) # Comparison to norm computed in MATLAB
69+
assert np.allclose(ct.norm(G4, p='inf', tol=1e-9), 4.276759162964244) # Comparison to norm computed in MATLAB
70+
assert np.allclose(ct.norm(G4, p=2), 2.237461821810309) # Comparison to norm computed in MATLAB
6071

6172
Gd4 = ct.sample_system(G4, 0.1)
62-
assert np.allclose(ct.norm(Gd4, p='inf', tol=1e-9, print_warning=False), 4.276759162964228) # Comparison to norm computed in MATLAB
63-
assert np.allclose(ct.norm(Gd4, p=2, print_warning=False), 0.707434962289554) # Comparison to norm computed in MATLAB
73+
assert np.allclose(ct.norm(Gd4, p='inf', tol=1e-9), 4.276759162964228) # Comparison to norm computed in MATLAB
74+
assert np.allclose(ct.norm(Gd4, p=2), 0.707434962289554) # Comparison to norm computed in MATLAB

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy