Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdd95f35

Browse files
authored
Merge pull request#729 from roryyorke/rory/linfnorm
ENH: add `linform` to compute linear system L-infinity norm
2 parents46b3c53 +02b3451 commitdd95f35

File tree

2 files changed

+117
-2
lines changed

2 files changed

+117
-2
lines changed

‎control/statesp.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
fromnumpy.linalgimportsolve,eigvals,matrix_rank
5656
fromnumpy.linalg.linalgimportLinAlgError
5757
importscipyassp
58+
importscipy.linalg
5859
fromscipy.signalimportcont2discrete
5960
fromscipy.signalimportStateSpaceassignalStateSpace
6061
fromwarningsimportwarn
@@ -65,7 +66,12 @@
6566
from .importconfig
6667
fromcopyimportdeepcopy
6768

68-
__all__= ['StateSpace','tf2ss','ssdata']
69+
try:
70+
fromslycotimportab13dd
71+
exceptImportError:
72+
ab13dd=None
73+
74+
__all__= ['StateSpace','tf2ss','ssdata','linfnorm']
6975

7076
# Define module default parameter values
7177
_statesp_defaults= {
@@ -1895,3 +1901,61 @@ def ssdata(sys):
18951901
"""
18961902
ss=_convert_to_statespace(sys)
18971903
returnss.A,ss.B,ss.C,ss.D
1904+
1905+
1906+
deflinfnorm(sys,tol=1e-10):
1907+
"""L-infinity norm of a linear system
1908+
1909+
Parameters
1910+
----------
1911+
sys : LTI (StateSpace or TransferFunction)
1912+
system to evalute L-infinity norm of
1913+
tol : real scalar
1914+
tolerance on norm estimate
1915+
1916+
Returns
1917+
-------
1918+
gpeak : non-negative scalar
1919+
L-infinity norm
1920+
fpeak : non-negative scalar
1921+
Frequency, in rad/s, at which gpeak occurs
1922+
1923+
For stable systems, the L-infinity and H-infinity norms are equal;
1924+
for unstable systems, the H-infinity norm is infinite, while the
1925+
L-infinity norm is finite if the system has no poles on the
1926+
imaginary axis.
1927+
1928+
See also
1929+
--------
1930+
slycot.ab13dd : the Slycot routine linfnorm that does the calculation
1931+
"""
1932+
1933+
ifab13ddisNone:
1934+
raiseControlSlycot("Can't find slycot module 'ab13dd'")
1935+
1936+
a,b,c,d=ssdata(_convert_to_statespace(sys))
1937+
e=np.eye(a.shape[0])
1938+
1939+
n=a.shape[0]
1940+
m=b.shape[1]
1941+
p=c.shape[0]
1942+
1943+
ifn==0:
1944+
# ab13dd doesn't accept empty A, B, C, D;
1945+
# static gain case is easy enough to compute
1946+
gpeak=scipy.linalg.svdvals(d)[0]
1947+
# max svd is constant with freq; arbitrarily choose 0 as peak
1948+
fpeak=0
1949+
returngpeak,fpeak
1950+
1951+
dico='C'ifsys.isctime()else'D'
1952+
jobe='I'
1953+
equil='S'
1954+
jobd='Z'ifall(0==d.flat)else'D'
1955+
1956+
gpeak,fpeak=ab13dd(dico,jobe,equil,jobd,n,m,p,a,e,b,c,d,tol)
1957+
1958+
ifdico=='D':
1959+
fpeak/=sys.dt
1960+
1961+
returngpeak,fpeak

‎control/tests/statesp_test.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
fromcontrol.dtimeimportsample_system
2020
fromcontrol.ltiimportevalfr
2121
fromcontrol.statespimportStateSpace,_convert_to_statespace,tf2ss, \
22-
_statesp_defaults,_rss_generate
22+
_statesp_defaults,_rss_generate,linfnorm
2323
fromcontrol.iosysimportss,rss,drss
2424
fromcontrol.tests.conftestimportismatarrayout,slycotonly
2525
fromcontrol.xferfcnimportTransferFunction,ss2tf
2626

27+
2728
from .conftestimporteditsdefaults
2829

30+
2931
classTestStateSpace:
3032
"""Tests for the StateSpace class."""
3133

@@ -1107,3 +1109,52 @@ def test_latex_repr_testsize(editsdefaults):
11071109

11081110
gstatic=ss([], [], [],1)
11091111
assertgstatic._repr_latex_()isNone
1112+
1113+
1114+
classTestLinfnorm:
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+
defct_siso(self,request):
1129+
name,systype,sysargs,refgpeak,reffpeak=request.param
1130+
returnsystype(*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+
defdt_siso(self,request):
1136+
name,systype,sysargs,dt,refgpeak,reffpeak=request.param
1137+
returnct.c2d(systype(*sysargs),dt),refgpeak,reffpeak
1138+
1139+
@slycotonly
1140+
deftest_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+
deftest_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+
deftest_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

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp