1 ## Copyright (C) 2009, 2010, 2012 Lukas F. Reichlin
3 ## This file is part of LTI Syncope.
5 ## LTI Syncope is free software: you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation, either version 3 of the License, or
8 ## (at your option) any later version.
10 ## LTI Syncope is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ## GNU General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with LTI Syncope. If not, see <http://www.gnu.org/licenses/>.
19 ## @deftypefn {Function File} {@var{bool} =} isstabilizable (@var{sys})
20 ## @deftypefnx {Function File} {@var{bool} =} isstabilizable (@var{sys}, @var{tol})
21 ## @deftypefnx {Function File} {@var{bool} =} isstabilizable (@var{a}, @var{b})
22 ## @deftypefnx {Function File} {@var{bool} =} isstabilizable (@var{a}, @var{b}, @var{e})
23 ## @deftypefnx {Function File} {@var{bool} =} isstabilizable (@var{a}, @var{b}, @var{[]}, @var{tol})
24 ## @deftypefnx {Function File} {@var{bool} =} isstabilizable (@var{a}, @var{b}, @var{e}, @var{tol})
25 ## @deftypefnx {Function File} {@var{bool} =} isstabilizable (@var{a}, @var{b}, @var{[]}, @var{[]}, @var{dflg})
26 ## @deftypefnx {Function File} {@var{bool} =} isstabilizable (@var{a}, @var{b}, @var{e}, @var{[]}, @var{dflg})
27 ## @deftypefnx {Function File} {@var{bool} =} isstabilizable (@var{a}, @var{b}, @var{[]}, @var{tol}, @var{dflg})
28 ## @deftypefnx {Function File} {@var{bool} =} isstabilizable (@var{a}, @var{b}, @var{e}, @var{tol}, @var{dflg})
29 ## Logical check for system stabilizability.
30 ## All unstable modes must be controllable or all uncontrollable states must be stable.
37 ## State transition matrix.
42 ## If @var{e} is empty @code{[]} or not specified, an identity matrix is assumed.
44 ## Optional tolerance for stability. Default value is 0.
46 ## Matrices (@var{a}, @var{b}) are part of a continuous-time system. Default Value.
48 ## Matrices (@var{a}, @var{b}) are part of a discrete-time system.
54 ## System is not stabilizable.
56 ## System is stabilizable.
59 ## @strong{Algorithm}@*
60 ## Uses SLICOT AB01OD and TG01HD by courtesy of
61 ## @uref{http://www.slicot.org, NICONET e.V.}
64 ## * Calculate staircase form (SLICOT AB01OD)
65 ## * Extract unobservable part of state transition matrix
66 ## * Calculate eigenvalues of unobservable part
68 ## real (ev) < -tol*(1 + abs (ev)) continuous-time
69 ## abs (ev) < 1 - tol discrete-time
72 ## @seealso{isdetectable, isstable, isctrb, isobsv}
75 ## Author: Lukas Reichlin <lukas.reichlin@gmail.com>
76 ## Created: October 2009
79 function bool = isstabilizable (a, b = [], e = [], tol = [], dflg = 0)
81 if (nargin < 1 || nargin > 5)
83 elseif (isa (a, "lti")) # isstabilizable (sys), isstabilizable (sys, tol)
89 [a, b, c, d, e] = dssdata (a, []);
90 elseif (nargin == 1) # isstabilizable (a, b, ...)
92 elseif (! is_real_square_matrix (a) || rows (a) != rows (b))
93 error ("isstabilizable: a must be square and conformal to b");
94 elseif (! isempty (e) && (! is_real_square_matrix (e) || ! size_equal (a, e)))
95 error ("isstabilizable: e must be square and conformal to a");
99 tol = 0; # default tolerance
100 elseif (! is_real_scalar (tol))
101 error ("isstabilizable: tol must be a real scalar");
105 ## controllability staircase form
106 [ac, ~, ~, ncont] = slab01od (a, b, tol);
108 ## extract uncontrollable part of staircase form
109 uncont_idx = ncont+1 : rows (a);
110 auncont = ac(uncont_idx, uncont_idx);
112 ## calculate poles of uncontrollable part
115 ## controllability staircase form - output matrix c has no influence
116 [ac, ec, ~, ~, ~, ~, ncont] = sltg01hd (a, e, b, zeros (1, columns (a)), tol);
118 ## extract uncontrollable part of staircase form
119 uncont_idx = ncont+1 : rows (a);
120 auncont = ac(uncont_idx, uncont_idx);
121 euncont = ec(uncont_idx, uncont_idx);
123 ## calculate poles of uncontrollable part
124 pol = eig (auncont, euncont);
126 ## remove infinite poles
127 tolinf = norm ([auncont, euncont], 2);
128 idx = find (abs (pol) < tolinf/eps);
132 ## check whether uncontrollable poles are stable
133 bool = __is_stable__ (pol, ! dflg, tol);