4242# External packages and modules
4343import numpy as np
4444import scipy as sp
45+ import warnings
4546from . import statesp
4647from .exception import ControlSlycot , ControlArgument , ControlDimension
4748
@@ -219,7 +220,7 @@ def place_varga(A, B, p, dtime=False, alpha=None):
219220 return - F
220221
221222# Contributed by Roberto Bucher <roberto.bucher@supsi.ch>
222- def acker (A , B , poles ):
223+ def acker (A , B , poles , return_type = np . matrix ):
223224 """Pole placement using Ackermann method
224225
225226 Call:
@@ -238,12 +239,18 @@ def acker(A, B, poles):
238239 Gains such that A - B K has given eigenvalues
239240
240241 """
242+ # If return_type is np.matrix, issue a pending deprecation warning
243+ if (return_type is np .matrix ):
244+ warnings .warn ("Returning numpy.matrix, soon to be deprecated; "
245+ "make sure calling code can handle nparray." ,
246+ stacklevel = 2 )
247+
241248 # Convert the inputs to matrices (arrays)
242- a = np . array (A )
243- b = np . array (B )
249+ a = statesp . ssmatrix (A )
250+ b = statesp . ssmatrix (B )
244251
245252 # Make sure the system is controllable
246- ct = ctrb (A , B )
253+ ct = ctrb (A , B , return_type = np . ndarray )
247254 if np .linalg .matrix_rank (ct ) != a .shape [0 ]:
248255 raise ValueError ("System not reachable; pole placement invalid" )
249256
@@ -258,7 +265,7 @@ def acker(A, B, poles):
258265 K = np .linalg .solve (ct , pmat )
259266
260267 K = K [- 1 ][:] # Extract the last row
261- return K
268+ return K . view ( type = return_type )
262269
263270def lqr (* args , ** keywords ):
264271 """lqr(A, B, Q, R[, N])
@@ -368,14 +375,18 @@ def lqr(*args, **keywords):
368375
369376 return K , S , E
370377
371- def ctrb (A ,B ):
378+
379+ def ctrb (A , B , return_type = np .matrix ):
372380 """Controllabilty matrix
373381
374382 Parameters
375383 ----------
376384 A, B: array_like or string
377385 Dynamics and input matrix of the system
378386
387+ return_type: nparray subtype, optional (default = numpy.matrix)
388+ Set the ndarray subtype for the return value
389+
379390 Returns
380391 -------
381392 C: matrix
@@ -386,25 +397,36 @@ def ctrb(A,B):
386397 >>> C = ctrb(A, B)
387398
388399 """
400+ # If return_type is np.matrix, issue a pending deprecation warning
401+ if (return_type is np .matrix ):
402+ warnings .warn ("Returning numpy.matrix, soon to be deprecated; "
403+ "make sure calling code can handle nparray." ,
404+ stacklevel = 2 )
389405
390406 # Convert input parameters to matrices (if they aren't already)
391- amat = np . array (A )
392- bmat = np . array (B )
407+ amat = statesp . ssmatrix (A )
408+ bmat = statesp . ssmatrix (B )
393409 n = np .shape (amat )[0 ]
394410 # Construct the controllability matrix
395411 ctrb = bmat
396412 for i in range (1 , n ):
397413 ctrb = np .hstack ((ctrb , np .dot (np .linalg .matrix_power (amat , i ), bmat )))
398- return ctrb
399414
400- def obsv (A , C ):
415+ # Return the observability matrix in the desired type
416+ return ctrb .view (type = return_type )
417+
418+
419+ def obsv (A , C , return_type = np .matrix ):
401420 """Observability matrix
402421
403422 Parameters
404423 ----------
405424 A, C: array_like or string
406425 Dynamics and output matrix of the system
407426
427+ return_type: nparray subtype, optional (default = numpy.matrix)
428+ Set the ndarray subtype for the return value
429+
408430 Returns
409431 -------
410432 O: matrix
@@ -414,20 +436,28 @@ def obsv(A, C):
414436 --------
415437 >>> O = obsv(A, C)
416438
417- """
439+ """
440+ # If return_type is np.matrix, issue a pending deprecation warning
441+ if (return_type is np .matrix ):
442+ warnings .warn ("Returning numpy.matrix, soon to be deprecated; "
443+ "make sure calling code can handle nparray." ,
444+ stacklevel = 2 )
418445
419446 # Convert input parameters to matrices (if they aren't already)
420- amat = np . array (A )
421- cmat = np . array (C )
447+ amat = statesp . ssmatrix (A )
448+ cmat = statesp . ssmatrix (C )
422449 n = np .shape (amat )[0 ]
423450
424451 # Construct the controllability matrix
425452 obsv = cmat
426453 for i in range (1 , n ):
427454 obsv = np .vstack ((obsv , np .dot (cmat , np .linalg .matrix_power (amat , i ))))
428- return obsv
429455
430- def gram (sys ,type ):
456+ # Return the observability matrix in the desired type
457+ return obsv .view (type = return_type )
458+
459+
460+ def gram (sys , type , return_type = np .matrix ):
431461 """Gramian (controllability or observability)
432462
433463 Parameters
@@ -436,8 +466,9 @@ def gram(sys,type):
436466 State-space system to compute Gramian for
437467 type: String
438468 Type of desired computation.
439- `type` is either 'c' (controllability) or 'o' (observability). To compute the
440- Cholesky factors of gramians use 'cf' (controllability) or 'of' (observability)
469+ `type` is either 'c' (controllability) or 'o' (observability). To
470+ compute the Cholesky factors of gramians use 'cf' (controllability) or
471+ 'of' (observability)
441472
442473 Returns
443474 -------
@@ -463,6 +494,11 @@ def gram(sys,type):
463494 >>> Ro = gram(sys,'of'), where Wo=Ro'*Ro
464495
465496 """
497+ # If return_type is np.matrix, issue a pending deprecation warning
498+ if (return_type is np .matrix ):
499+ warnings .warn ("Returning numpy.matrix, soon to be deprecated; "
500+ "make sure calling code can handle nparray." ,
501+ stacklevel = 2 )
466502
467503 #Check for ss system object
468504 if not isinstance (sys ,statesp .StateSpace ):
@@ -501,7 +537,7 @@ def gram(sys,type):
501537 A = np .array (sys .A ) # convert to NumPy array for slycot
502538 X ,scale ,sep ,ferr ,w = sb03md (n , C , A , U , dico , job = 'X' , fact = 'N' , trana = tra )
503539 gram = X
504- return gram
540+ return gram . view ( type = return_type )
505541
506542 elif type == 'cf' or type == 'of' :
507543 #Compute cholesky factored gramian from slycot routine sb03od
@@ -524,4 +560,4 @@ def gram(sys,type):
524560 C [0 :n ,0 :m ] = sys .C .transpose ()
525561 X ,scale ,w = sb03od (n , m , A , Q , C .transpose (), dico , fact = 'N' , trans = tra )
526562 gram = X
527- return gram
563+ return gram . view ( type = return_type )
0 commit comments