@@ -411,7 +411,7 @@ def dlyap(A,Q,C=None,E=None):
411
411
412
412
#### Riccati equation solvers care and dare
413
413
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 ):
415
415
""" (X,L,G) = care(A,B,Q,R=None) solves the continuous-time algebraic Riccati
416
416
equation
417
417
@@ -527,7 +527,11 @@ def care(A,B,Q,R=None,S=None,E=None):
527
527
raise e
528
528
529
529
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 )
531
535
except ValueError as ve :
532
536
if ve .info < 0 or ve .info > 5 :
533
537
e = ValueError (ve .message )
@@ -613,8 +617,12 @@ def care(A,B,Q,R=None,S=None,E=None):
613
617
# Solve the generalized algebraic Riccati equation by calling the
614
618
# Slycot function sg02ad
615
619
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 )
618
626
except ValueError as ve :
619
627
if ve .info < 0 or ve .info > 7 :
620
628
e = ValueError (ve .message )
@@ -671,7 +679,7 @@ def care(A,B,Q,R=None,S=None,E=None):
671
679
else :
672
680
raise ControlArgument ("Invalid set of input parameters." )
673
681
674
- def dare (A ,B , Q , R , S = None ,E = None ):
682
+ def dare (A , B , Q , R , S = None , E = None , stabilizing = True ):
675
683
""" (X,L,G) = dare(A,B,Q,R) solves the discrete-time algebraic Riccati
676
684
equation
677
685
@@ -692,8 +700,8 @@ def dare(A,B,Q,R,S=None,E=None):
692
700
matrix :math:`G = (B^T X B + R)^{-1} (B^T X A + S^T)` and the closed loop
693
701
eigenvalues L, i.e., the eigenvalues of A - B G , E.
694
702
"""
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 )
697
705
else :
698
706
Rmat = asmatrix (R )
699
707
Qmat = asmatrix (Q )
@@ -702,7 +710,7 @@ def dare(A,B,Q,R,S=None,E=None):
702
710
L = eigvals (A - B .dot (G ))
703
711
return X , L , G
704
712
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 ):
706
714
# Make sure we can import required slycot routine
707
715
try :
708
716
from slycot import sb02md
@@ -795,7 +803,12 @@ def dare_old(A,B,Q,R,S=None,E=None):
795
803
raise e
796
804
797
805
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 )
799
812
except ValueError as ve :
800
813
if ve .info < 0 or ve .info > 5 :
801
814
e = ValueError (ve .message )
@@ -884,8 +897,12 @@ def dare_old(A,B,Q,R,S=None,E=None):
884
897
# Solve the generalized algebraic Riccati equation by calling the
885
898
# Slycot function sg02ad
886
899
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 )
889
906
except ValueError as ve :
890
907
if ve .info < 0 or ve .info > 7 :
891
908
e = ValueError (ve .message )
0 commit comments