3431
|
1 ## Copyright (C) 1993, 1994, 1995 John W. Eaton |
|
2 ## |
|
3 ## This file is part of Octave. |
|
4 ## |
|
5 ## Octave is free software; you can redistribute it and/or modify it |
|
6 ## under the terms of the GNU General Public License as published by the |
|
7 ## Free Software Foundation; either version 2, or (at your option) any |
|
8 ## later version. |
|
9 ## |
|
10 ## Octave is distributed in the hope that it will be useful, but WITHOUT |
|
11 ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
12 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
13 ## for more details. |
|
14 ## |
|
15 ## You should have received a copy of the GNU General Public License |
|
16 ## along with Octave; see the file COPYING. If not, write to the Free |
|
17 ## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. |
|
18 |
|
19 ## -*- texinfo -*- |
3500
|
20 ## @deftypefn {Function File} {} c2d (@var{sys}, @var{opt}, @var{T}) |
|
21 ## @deftypefnx {Function File} {} c2d (@var{sys}, @var{T}) |
3431
|
22 ## |
|
23 ## @strong{Inputs} |
|
24 ## @table @var |
|
25 ## @item sys |
|
26 ## system data structure (may have both continuous time and discrete |
|
27 ## time subsystems) |
|
28 ## @item opt |
|
29 ## string argument; conversion option (optional argument; |
|
30 ## may be omitted as shown above) |
|
31 ## @table @code |
|
32 ## @item "ex" |
|
33 ## use the matrix exponential (default) |
|
34 ## @item "bi" |
|
35 ## use the bilinear transformation |
|
36 ## @end table |
|
37 ## @example |
|
38 ## 2(z-1) |
|
39 ## s = ----- |
|
40 ## T(z+1) |
|
41 ## @end example |
|
42 ## FIXME: This option exits with an error if @var{sys} is not purely |
|
43 ## continuous. (The @code{ex} option can handle mixed systems.) |
|
44 ## @item @var{T} |
|
45 ## sampling time; required if sys is purely continuous. |
|
46 ## |
|
47 ## @strong{Note} If the 2nd argument is not a string, @code{c2d} assumes that |
|
48 ## the 2nd argument is @var{T} and performs appropriate argument checks. |
|
49 ## @end table |
|
50 ## |
|
51 ## @strong{Outputs} |
|
52 ## @var{dsys} discrete time equivalent via zero-order hold, |
|
53 ## sample each @var{T} sec. |
|
54 ## |
|
55 ## converts the system data structure describing |
|
56 ## @example |
|
57 ## . |
|
58 ## x = Ac x + Bc u |
|
59 ## @end example |
|
60 ## into a discrete time equivalent model |
|
61 ## @example |
|
62 ## x[n+1] = Ad x[n] + Bd u[n] |
|
63 ## @end example |
|
64 ## via the matrix exponential or bilinear transform |
|
65 ## |
|
66 ## @strong{Note} This function adds the suffix @code{_d} |
|
67 ## to the names of the new discrete states. |
|
68 ## @end deftypefn |
|
69 |
|
70 ## Author: R. Bruce Tenison <btenison@eng.auburn.edu> |
|
71 ## Created: October 1993 |
|
72 ## Updated by John Ingram for system data structure August 1996 |
|
73 |
|
74 function dsys = c2d (sys, opt, T) |
|
75 ## parse input arguments |
|
76 if(nargin < 1 | nargin > 3) |
|
77 usage("dsys=c2d(sys[,T])"); |
|
78 elseif (!is_struct(sys)) |
|
79 error("sys must be a system data structure"); |
|
80 elseif (nargin == 1) |
|
81 opt = "ex"; |
|
82 elseif (nargin == 2 & !isstr(opt) ) |
|
83 T = opt; |
|
84 opt = "ex"; |
|
85 endif |
|
86 |
|
87 ## check if sampling period T was passed. |
|
88 Ts = sysgettsam(sys); |
|
89 if(!exist("T")) |
|
90 T = Ts; |
|
91 if(T == 0) |
|
92 error("sys is purely continuous; no sampling period T provided"); |
|
93 endif |
|
94 elseif (T != Ts & Ts > 0) |
|
95 warning(["c2d: T=",num2str(T),", system tsam==",num2str(Ts), ... |
|
96 ": using T=", num2str(min(T,Ts))]); |
|
97 T = min(T,Ts); |
|
98 endif |
|
99 |
|
100 if (!is_sample(T)) |
|
101 error("sampling period T must be a postive, real scalar"); |
|
102 elseif( ! (strcmp(opt,"ex") | strcmp(opt,"bi") ) ) |
|
103 error(["invalid option passed: ",opt]) |
|
104 endif |
|
105 |
|
106 sys = sysupdate(sys,"ss"); |
|
107 [n,nz,m,p] = sysdimensions(sys); |
|
108 if(n == 0) |
|
109 dsys = syssetsignals(sys,"yd",ones(1:p)); |
|
110 elseif(strcmp(opt,"ex")); |
|
111 [aa,bb,cc,dd] = sys2ss(sys); |
|
112 crng= 1:n; |
|
113 drng = n+(1:nz); |
|
114 |
|
115 ## partition state equations into continuous, imaginary subsystems |
|
116 Ac = aa(crng,crng); |
|
117 Bc = bb(crng,:); |
|
118 if(nz == 0) |
|
119 Acd = Adc = Add = Bd = 0; |
|
120 else |
|
121 Acd = aa(crng,drng); |
|
122 Adc = aa(drng,crng); |
|
123 Add = aa(drng,drng); |
|
124 Bd = bb(drng,:); |
|
125 Bc = [Bc, Acd]; ## append discrete states as inputs to cont system |
|
126 endif |
|
127 |
|
128 ## convert state equations |
|
129 mat = [Ac, Bc; zeros(m+nz,n+nz+m)]; |
|
130 matexp = expm(mat * T); |
|
131 |
|
132 ## replace Ac |
|
133 aa(crng,crng) = matexp(crng,crng); ## discretized homegenous diff eqn |
|
134 |
|
135 ## replace Bc |
|
136 bb(crng,:) = matexp(crng,n+(1:m)); |
|
137 |
|
138 ## replace Acd |
|
139 if(nz) |
|
140 aa(crng,drng) = matexp(crng,n+m+(1:nz)); |
|
141 end |
|
142 |
|
143 stnames = sysgetsignals(sys,"st"); ## continuous states renamed below |
|
144 innames = sysgetsignals(sys,"in"); |
|
145 outnames = sysgetsignals(sys,"out"); |
|
146 outlist = 1:p; |
|
147 dsys = ss2sys(aa,bb,cc,dd,T,0,n+nz,stnames,innames, ... |
|
148 outnames,outlist); |
|
149 ## rename states |
|
150 for ii=1:n |
|
151 strval = sprintf("%s_d",sysgetsignals(dsys,"st",ii,1)); |
|
152 dsys = syssetsignals(dsys,"st",strval,ii); |
|
153 endfor |
|
154 |
|
155 elseif(strcmp(opt,"bi")) |
|
156 if(is_digital(sys)) |
|
157 error("c2d: system is already digital") |
|
158 else |
|
159 ## convert with bilinear transform |
|
160 [a,b,c,d,tsam,n,nz,stname,inname,outname,yd] = sys2ss(sys); |
|
161 IT = (2/T)*eye(size(a)); |
|
162 A = (IT+a)/(IT-a); |
|
163 iab = (IT-a)\b; |
|
164 tk=2/sqrt(T); |
|
165 B = tk*iab; |
|
166 C = tk*(c/(IT-a)); |
|
167 D = d + (c*iab); |
|
168 stnamed = strappend(stname,"_d"); |
|
169 dsys = ss2sys(A,B,C,D,T,0,rows(A),stnamed,inname,outname); |
|
170 endif |
|
171 else |
|
172 error(["Bad option=",opt]) |
|
173 endif |
|
174 |
|
175 endfunction |