Skip to content

Commit cf77e23

Browse files
author
Daniel Bankmann
committed
added option for computing anti-stabilizing solutions of Riccati equations
1 parent 31e6944 commit cf77e23

File tree

1 file changed

+28
-11
lines changed

1 file changed

+28
-11
lines changed

control/mateqn.py

+28-11
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ def dlyap(A,Q,C=None,E=None):
411411

412412
#### Riccati equation solvers care and dare
413413

414-
def care(A,B,Q,R=None,S=None,E=None):
414+
def care(A, B, Q, R=None, S=None, E=None, stabilizing=True):
415415
""" (X,L,G) = care(A,B,Q,R=None) solves the continuous-time algebraic Riccati
416416
equation
417417
@@ -527,7 +527,11 @@ def care(A,B,Q,R=None,S=None,E=None):
527527
raise e
528528

529529
try:
530-
X,rcond,w,S_o,U,A_inv = sb02md(n,A,G,Q,'C')
530+
if stabilizing:
531+
sort = 'S'
532+
else:
533+
sort = 'U'
534+
X, rcond, w, S_o, U, A_inv = sb02md(n, A, G, Q, 'C', sort=sort)
531535
except ValueError as ve:
532536
if ve.info < 0 or ve.info > 5:
533537
e = ValueError(ve.message)
@@ -613,8 +617,12 @@ def care(A,B,Q,R=None,S=None,E=None):
613617
# Solve the generalized algebraic Riccati equation by calling the
614618
# Slycot function sg02ad
615619
try:
616-
rcondu,X,alfar,alfai,beta,S_o,T,U,iwarn = \
617-
sg02ad('C','B','N','U','N','N','S','R',n,m,0,A,E,B,Q,R,S)
620+
if stabilizing:
621+
sort = 'S'
622+
else:
623+
sort = 'U'
624+
rcondu, X, alfar, alfai, beta, S_o, T, U, iwarn = \
625+
sg02ad('C', 'B', 'N', 'U', 'N', 'N', sort, 'R', n, m, 0, A, E, B, Q, R, S)
618626
except ValueError as ve:
619627
if ve.info < 0 or ve.info > 7:
620628
e = ValueError(ve.message)
@@ -671,7 +679,7 @@ def care(A,B,Q,R=None,S=None,E=None):
671679
else:
672680
raise ControlArgument("Invalid set of input parameters.")
673681

674-
def dare(A,B,Q,R,S=None,E=None):
682+
def dare(A, B, Q, R, S=None, E=None, stabilizing=True):
675683
""" (X,L,G) = dare(A,B,Q,R) solves the discrete-time algebraic Riccati
676684
equation
677685
@@ -692,8 +700,8 @@ def dare(A,B,Q,R,S=None,E=None):
692700
matrix :math:`G = (B^T X B + R)^{-1} (B^T X A + S^T)` and the closed loop
693701
eigenvalues L, i.e., the eigenvalues of A - B G , E.
694702
"""
695-
if S is not None or E is not None:
696-
return dare_old(A, B, Q, R, S, E)
703+
if S is not None or E is not None or not stabilizing:
704+
return dare_old(A, B, Q, R, S, E, stabilizing)
697705
else:
698706
Rmat = asmatrix(R)
699707
Qmat = asmatrix(Q)
@@ -702,7 +710,7 @@ def dare(A,B,Q,R,S=None,E=None):
702710
L = eigvals(A - B.dot(G))
703711
return X, L, G
704712

705-
def dare_old(A,B,Q,R,S=None,E=None):
713+
def dare_old(A, B, Q, R, S=None, E=None, stabilizing=True):
706714
# Make sure we can import required slycot routine
707715
try:
708716
from slycot import sb02md
@@ -795,7 +803,12 @@ def dare_old(A,B,Q,R,S=None,E=None):
795803
raise e
796804

797805
try:
798-
X,rcond,w,S,U,A_inv = sb02md(n,A,G,Q,'D')
806+
if stabilizing:
807+
sort = 'S'
808+
else:
809+
sort = 'U'
810+
811+
X, rcond, w, S, U, A_inv = sb02md(n, A, G, Q, 'D', sort=sort)
799812
except ValueError as ve:
800813
if ve.info < 0 or ve.info > 5:
801814
e = ValueError(ve.message)
@@ -884,8 +897,12 @@ def dare_old(A,B,Q,R,S=None,E=None):
884897
# Solve the generalized algebraic Riccati equation by calling the
885898
# Slycot function sg02ad
886899
try:
887-
rcondu,X,alfar,alfai,beta,S_o,T,U,iwarn = \
888-
sg02ad('D','B','N','U','N','N','S','R',n,m,0,A,E,B,Q,R,S)
900+
if stabilizing:
901+
sort = 'S'
902+
else:
903+
sort = 'U'
904+
rcondu, X, alfar, alfai, beta, S_o, T, U, iwarn = \
905+
sg02ad('D', 'B', 'N', 'U', 'N', 'N', sort, 'R', n, m, 0, A, E, B, Q, R, S)
889906
except ValueError as ve:
890907
if ve.info < 0 or ve.info > 7:
891908
e = ValueError(ve.message)

0 commit comments

Comments
 (0)