@@ -475,6 +475,10 @@ def lqr(*args, **keywords):
475
475
State and input weight matrices
476
476
N : 2D array, optional
477
477
Cross weight matrix
478
+ method : str, optional
479
+ Set the method used for computing the result. Current methods are
480
+ 'slycot' and 'scipy'. If set to None (default), try 'slycot' first
481
+ and then 'scipy'.
478
482
479
483
Returns
480
484
-------
@@ -498,14 +502,23 @@ def lqr(*args, **keywords):
498
502
--------
499
503
>>> K, S, E = lqr(sys, Q, R, [N])
500
504
>>> K, S, E = lqr(A, B, Q, R, [N])
505
+
501
506
"""
502
507
503
- # Make sure that SLICOT is installed
504
- try :
505
- from slycot import sb02md
506
- from slycot import sb02mt
507
- except ImportError :
508
- raise ControlSlycot ("can't find slycot module 'sb02md' or 'sb02nt'" )
508
+ # Figure out what method to use
509
+ method = keywords .get ('method' , None )
510
+ if method == 'slycot' or method is None :
511
+ # Make sure that SLICOT is installed
512
+ try :
513
+ from slycot import sb02md
514
+ from slycot import sb02mt
515
+ method = 'slycot'
516
+ except ImportError :
517
+ if method == 'slycot' :
518
+ raise ControlSlycot (
519
+ "can't find slycot module 'sb02md' or 'sb02nt'" )
520
+ else :
521
+ method = 'scipy'
509
522
510
523
#
511
524
# Process the arguments and figure out what inputs we received
@@ -546,18 +559,28 @@ def lqr(*args, **keywords):
546
559
N .shape [0 ] != nstates or N .shape [1 ] != ninputs ):
547
560
raise ControlDimension ("incorrect weighting matrix dimensions" )
548
561
549
- # Compute the G matrix required by SB02MD
550
- A_b , B_b , Q_b , R_b , L_b , ipiv , oufact , G = \
551
- sb02mt (nstates , ninputs , B , R , A , Q , N , jobl = 'N' )
562
+ if method == 'slycot' :
563
+ # Compute the G matrix required by SB02MD
564
+ A_b , B_b , Q_b , R_b , L_b , ipiv , oufact , G = \
565
+ sb02mt (nstates , ninputs , B , R , A , Q , N , jobl = 'N' )
552
566
553
- # Call the SLICOT function
554
- X , rcond , w , S , U , A_inv = sb02md (nstates , A_b , G , Q_b , 'C' )
567
+ # Call the SLICOT function
568
+ X , rcond , w , S , U , A_inv = sb02md (nstates , A_b , G , Q_b , 'C' )
555
569
556
- # Now compute the return value
557
- # We assume that R is positive definite and, hence, invertible
558
- K = np .linalg .solve (R , B .T @ X + N .T )
559
- S = X
560
- E = w [0 :nstates ]
570
+ # Now compute the return value
571
+ # We assume that R is positive definite and, hence, invertible
572
+ K = np .linalg .solve (R , np .dot (B .T , X ) + N .T )
573
+ S = X
574
+ E = w [0 :nstates ]
575
+
576
+ elif method == 'scipy' :
577
+ import scipy as sp
578
+ S = sp .linalg .solve_continuous_are (A , B , Q , R , s = N )
579
+ K = np .linalg .solve (R , B .T @ S + N .T )
580
+ E , _ = np .linalg .eig (A - B @ K )
581
+
582
+ else :
583
+ raise ValueError ("unknown method: %s" % method )
561
584
562
585
return _ssmatrix (K ), _ssmatrix (S ), E
563
586
0 commit comments