Skip to content

Commit a1f27db

Browse files
author
Henrik Sandberg
committed
New function for LTI system norm computation
1 parent af4f8a7 commit a1f27db

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

control/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
from .config import *
102102
from .sisotool import *
103103
from .passivity import *
104+
from .sysnorm import *
104105

105106
# Exceptions
106107
from .exception import *

control/sysnorm.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Created on Thu Dec 21 08:06:12 2023
4+
5+
@author: hsan
6+
"""
7+
8+
import numpy as np
9+
import numpy.linalg as la
10+
11+
import control as ct
12+
13+
#------------------------------------------------------------------------------
14+
15+
def norm(system, p=2, tol=1e-6):
16+
"""Computes H_2 (p=2) or L_infinity (p="inf", tolerance tol) norm of system."""
17+
G = ct.ss(system)
18+
A = G.A
19+
B = G.B
20+
C = G.C
21+
D = G.D
22+
23+
if p == 2: # H_2-norm
24+
if G.isctime():
25+
if (D != 0).any() or any(G.poles().real >= 0):
26+
return float('inf')
27+
else:
28+
P = ct.lyap(A, B@B.T)
29+
return np.sqrt(np.trace(C@P@C.T))
30+
elif G.isdtime():
31+
if any(abs(G.poles()) >= 1):
32+
return float('inf')
33+
else:
34+
P = ct.dlyap(A, B@B.T)
35+
return np.sqrt(np.trace(C@P@C.T + D@D.T))
36+
37+
elif p == "inf": # L_infinity-norm
38+
def Hamilton_matrix(gamma):
39+
"""Constructs Hamiltonian matrix."""
40+
R = Ip*gamma**2 - D.T@D
41+
invR = la.inv(R)
42+
return np.block([[A+B@invR@D.T@C, B@invR@B.T], [-C.T@(Ip+D@invR@D.T)@C, -(A+B@invR@D.T@C).T]])
43+
44+
if G.isdtime(): # Bilinear transformation to s-plane
45+
Ad = A
46+
Bd = B
47+
Cd = C
48+
Dd = D
49+
In = np.eye(len(Ad))
50+
Adinv = la.inv(Ad+In)
51+
A = 2*(Ad-In)@Adinv
52+
B = 2*Adinv@Bd
53+
C = 2*Cd@Adinv
54+
D = Dd - Cd@Adinv@Bd
55+
56+
if any(np.isclose(la.eigvals(A).real, 0.0)):
57+
return float('inf')
58+
59+
gaml = la.norm(D,ord=2) # Lower bound
60+
gamu = max(1.0, 2.0*gaml) # Candidate upper bound
61+
Ip = np.eye(len(D))
62+
63+
while any(np.isclose(la.eigvals(Hamilton_matrix(gamu)).real, 0.0)): # Find an upper bound
64+
gamu *= 2.0
65+
66+
while (gamu-gaml)/gamu > tol:
67+
gam = (gamu+gaml)/2.0
68+
if any(np.isclose(la.eigvals(Hamilton_matrix(gam)).real, 0.0)):
69+
gaml = gam
70+
else:
71+
gamu = gam
72+
return gam
73+
else:
74+
# Norm computation only supported for p=2 and p='inf'
75+
return None

0 commit comments

Comments
 (0)