Skip to content

Commit 82f3fe3

Browse files
Merge pull request #941 from Jpickard1/main
Improved speed of ctrb and obsv functions
2 parents f08ad6c + f8ba0d9 commit 82f3fe3

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

control/statefbk.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -990,13 +990,15 @@ def _control_output(t, states, inputs, params):
990990
return ctrl, closed
991991

992992

993-
def ctrb(A, B):
993+
def ctrb(A, B, t=None):
994994
"""Controllabilty matrix.
995995
996996
Parameters
997997
----------
998998
A, B : array_like or string
999999
Dynamics and input matrix of the system
1000+
t : None or integer
1001+
maximum time horizon of the controllability matrix, max = A.shape[0]
10001002
10011003
Returns
10021004
-------
@@ -1016,22 +1018,30 @@ def ctrb(A, B):
10161018
amat = _ssmatrix(A)
10171019
bmat = _ssmatrix(B)
10181020
n = np.shape(amat)[0]
1021+
m = np.shape(bmat)[1]
1022+
1023+
if t is None or t > n:
1024+
t = n
10191025

10201026
# Construct the controllability matrix
1021-
ctrb = np.hstack(
1022-
[bmat] + [np.linalg.matrix_power(amat, i) @ bmat
1023-
for i in range(1, n)])
1027+
ctrb = np.zeros((n, t * m))
1028+
ctrb[:, :m] = bmat
1029+
for k in range(1, t):
1030+
ctrb[:, k * m:(k + 1) * m] = np.dot(amat, ctrb[:, (k - 1) * m:k * m])
1031+
10241032
return _ssmatrix(ctrb)
10251033

10261034

1027-
def obsv(A, C):
1035+
def obsv(A, C, t=None):
10281036
"""Observability matrix.
10291037
10301038
Parameters
10311039
----------
10321040
A, C : array_like or string
10331041
Dynamics and output matrix of the system
1034-
1042+
t : None or integer
1043+
maximum time horizon of the controllability matrix, max = A.shape[0]
1044+
10351045
Returns
10361046
-------
10371047
O : 2D array (or matrix)
@@ -1050,10 +1060,18 @@ def obsv(A, C):
10501060
amat = _ssmatrix(A)
10511061
cmat = _ssmatrix(C)
10521062
n = np.shape(amat)[0]
1063+
p = np.shape(cmat)[0]
1064+
1065+
if t is None or t > n:
1066+
t = n
10531067

10541068
# Construct the observability matrix
1055-
obsv = np.vstack([cmat] + [cmat @ np.linalg.matrix_power(amat, i)
1056-
for i in range(1, n)])
1069+
obsv = np.zeros((t * p, n))
1070+
obsv[:p, :] = cmat
1071+
1072+
for k in range(1, t):
1073+
obsv[k * p:(k + 1) * p, :] = np.dot(obsv[(k - 1) * p:k * p, :], amat)
1074+
10571075
return _ssmatrix(obsv)
10581076

10591077

control/tests/statefbk_test.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ def testCtrbMIMO(self):
4949
Wc = ctrb(A, B)
5050
np.testing.assert_array_almost_equal(Wc, Wctrue)
5151

52+
def testCtrbT(self):
53+
A = np.array([[1., 2.], [3., 4.]])
54+
B = np.array([[5., 6.], [7., 8.]])
55+
t = 1
56+
Wctrue = np.array([[5., 6.], [7., 8.]])
57+
Wc = ctrb(A, B, t=t)
58+
np.testing.assert_array_almost_equal(Wc, Wctrue)
59+
5260
def testObsvSISO(self):
5361
A = np.array([[1., 2.], [3., 4.]])
5462
C = np.array([[5., 7.]])
@@ -62,6 +70,14 @@ def testObsvMIMO(self):
6270
Wotrue = np.array([[5., 6.], [7., 8.], [23., 34.], [31., 46.]])
6371
Wo = obsv(A, C)
6472
np.testing.assert_array_almost_equal(Wo, Wotrue)
73+
74+
def testObsvT(self):
75+
A = np.array([[1., 2.], [3., 4.]])
76+
C = np.array([[5., 6.], [7., 8.]])
77+
t = 1
78+
Wotrue = np.array([[5., 6.], [7., 8.]])
79+
Wo = obsv(A, C, t=t)
80+
np.testing.assert_array_almost_equal(Wo, Wotrue)
6581

6682
def testCtrbObsvDuality(self):
6783
A = np.array([[1.2, -2.3], [3.4, -4.5]])

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