3430
|
1 ## Copyright (C) 1996, 1998 Auburn University. All rights reserved. |
|
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} {} sysconnect (@var{sys}, @var{out_idx}, @var{in_idx}, @var{order}, @var{tol}) |
3430
|
21 ## Close the loop from specified outputs to respective specified inputs |
|
22 ## |
|
23 ## @strong{Inputs} |
|
24 ## @table @var |
|
25 ## @item sys |
|
26 ## system data structure |
|
27 ## @item out_idx |
|
28 ## @itemx in_idx |
3462
|
29 ## names or indices of signals to connect (see @code{sysidx}). |
|
30 ## The output specified by @math{out_idx(ii)} is connected to the input |
|
31 ## specified by @math{in_idx(ii)}. |
3430
|
32 ## @item order |
|
33 ## logical flag (default = 0) |
|
34 ## @table @code |
|
35 ## @item 0 |
|
36 ## leave inputs and outputs in their original order |
|
37 ## @item 1 |
|
38 ## permute inputs and outputs to the order shown in the diagram below |
|
39 ## @end table |
|
40 ## @item tol |
|
41 ## tolerance for singularities in algebraic loops default: 200@var{eps} |
|
42 ## @end table |
|
43 ## |
|
44 ## @strong{Outputs} |
|
45 ## @var{sys}: resulting closed loop system. |
|
46 ## |
|
47 ## @strong{Method} |
|
48 ## @code{sysconnect} internally permutes selected inputs, outputs as shown |
|
49 ## below, closes the loop, and then permutes inputs and outputs back to their |
|
50 ## original order |
|
51 ## @example |
|
52 ## @group |
|
53 ## ____________________ |
|
54 ## u_1 ----->| |----> y_1 |
|
55 ## | sys | |
|
56 ## old u_2 | | |
|
57 ## u_2* ---->(+)--->| |----->y_2 |
|
58 ## (in_idx) ^ -------------------| | (out_idx) |
|
59 ## | | |
|
60 ## ------------------------------- |
|
61 ## @end group |
|
62 ## @end example |
|
63 ## The input that has the summing junction added to it has an * added to |
|
64 ## the end of the input name. |
|
65 ## @end deftypefn |
|
66 |
|
67 ## Author: A. S. Hodel <a.s.hodel@eng.auburn.edu> |
|
68 ## Created: August 1995 |
|
69 ## modified by John Ingram July 1996 |
|
70 |
|
71 function sys = sysconnect (sys, output_list, input_list, order, tol) |
|
72 |
|
73 if( (nargin < 3) | (nargin > 5) ) |
|
74 usage("retsys = sysconnect(sys,output_list,input_list[,order,tol])"); |
|
75 endif |
|
76 |
|
77 ## check order |
|
78 if(nargin <= 3) |
|
79 order = 0; |
|
80 elseif( (order != 0) & (order != 1) ) |
|
81 error("sysconnect: order must be either 0 or 1") |
|
82 endif |
|
83 |
|
84 if (nargin <= 4) |
|
85 tol = 200*eps; |
|
86 elseif( !is_sample(tol) ) |
|
87 error("sysconnect: tol must be a positive scalar"); |
|
88 elseif(tol > 1e2*sqrt(eps)) |
|
89 warning(["sysconnect: tol set to large value=",num2str(tol), ... |
|
90 ", eps=",num2str(eps)]) |
|
91 endif |
|
92 |
3462
|
93 ## convert signal names to indices |
|
94 if(is_signal_list(input_list) | isstr(input_list)) |
|
95 input_list = sysidx(sys,"in",input_list); |
|
96 endif |
|
97 if(is_signal_list(output_list) | isstr(output_list)) |
|
98 output_list = sysidx(sys,"out",output_list); |
|
99 endif |
|
100 |
3430
|
101 ## verify sizes,format of input, output lists |
|
102 if( min(size(output_list))*min(size(input_list)) != 1) |
|
103 error("output_list and input_list must be vectors"); |
|
104 else |
|
105 lo = length(output_list); |
|
106 li = length(input_list); |
|
107 if(lo != li) |
|
108 error("output_list and input_list must be of the same length") |
|
109 endif |
|
110 |
|
111 if(is_duplicate_entry(output_list) | is_duplicate_entry(input_list) ) |
|
112 error("duplicate entry in input_list and/or output_list"); |
|
113 endif |
|
114 endif |
|
115 |
|
116 [nc,nz,mm,pp] = sysdimensions(sys); |
|
117 nn = nc+nz; |
|
118 |
|
119 if( !is_struct(sys)) |
|
120 error("sys must be in structured system form") |
|
121 elseif(pp < li) |
|
122 error(["length(output_list)=",num2str(li),", sys has only ", ... |
|
123 num2str(pp),"system outputs"]) |
|
124 elseif(mm < li) |
|
125 error(["length(input_list)=",num2str(li),", sys has only ", ... |
|
126 num2str(mm),"system inputs"]) |
|
127 endif |
|
128 |
|
129 ## check that there are enough inputs/outputs in the system for the lists |
|
130 if(max(input_list) > mm) |
|
131 error("max(input_list) exceeds the number of inputs"); |
|
132 elseif(max(output_list) > pp) |
|
133 error("max(output_list) exceeds the number of outputs"); |
|
134 endif |
|
135 |
|
136 output_list = reshape(output_list,1,length(output_list)); |
|
137 |
|
138 ## make sure we're in state space form |
|
139 sys = sysupdate (sys, "ss"); |
|
140 |
|
141 ## permute rows and columns of B,C,D matrices into pseudo-dgkf form... |
|
142 all_inputs = sysreorder(mm,input_list); |
|
143 all_outputs = sysreorder(pp,output_list); |
|
144 |
|
145 [aa,bb,cc,dd] = sys2ss(sys); |
|
146 bb = bb(:,all_inputs); |
|
147 cc = cc(all_outputs,:); |
|
148 dd = dd(all_outputs,all_inputs); |
|
149 |
|
150 yd = sysgetsignals(sys,"yd"); |
|
151 yd = yd(all_outputs); |
|
152 |
|
153 ## m1, p1 = number of inputs, outputs that are not being connected |
|
154 m1 = mm-li; |
|
155 p1 = pp-li; |
|
156 |
|
157 ## m2, p2: 1st column, row of B, C that is being connected |
|
158 m2 = m1+1; |
|
159 p2 = p1+1; |
|
160 |
|
161 ## partition system into a DGKF-like form; the loop is closed around |
|
162 ## B2, C2 |
|
163 if(m1 > 0) |
|
164 B1 = bb(:,1:m1); |
|
165 D21= dd(p2:pp,1:m1); |
|
166 endif |
|
167 B2 = bb(:,m2:mm); |
|
168 if(p1 > 0) |
|
169 C1 = cc(1:p1,:); |
|
170 D12= dd(1:p1,m2:mm); |
|
171 endif |
|
172 C2 = cc(p2:pp,:); |
|
173 if(m1*p1 > 0) |
|
174 D11= dd(1:p1,1:m1); |
|
175 endif |
|
176 D22= dd(p2:pp,m2:mm); |
|
177 |
|
178 if(norm(D22)) |
|
179 warning("sysconnect: possible algebraic loop, D22 non-zero"); |
|
180 D22i = (eye(size(D22))-D22); |
|
181 C2h = D22i\C2; |
|
182 if(m1 > 0) |
|
183 D21h = D22i\D21; |
|
184 endif |
|
185 D22h = D22i\D22; |
|
186 else |
|
187 C2h = C2; |
|
188 if(m1 > 0) |
|
189 D21h = D21; |
|
190 endif |
|
191 D22h = D22; |
|
192 |
|
193 endif |
|
194 |
|
195 ## check cont state -> disc output -> cont state |
|
196 dyi = find(yd(p2:pp)); |
|
197 |
|
198 ## disp("sysconnect: dyi=") |
|
199 ## dyi |
|
200 ## nc |
|
201 ## disp("/sysconnect"); |
|
202 |
|
203 if( (nc > 0) & find(dyi > 0) ) |
|
204 B2con = B2(1:nc,dyi); # connection to cont states |
|
205 C2hd = C2h(dyi,1:nc); # cont states -> outputs |
|
206 else |
|
207 B2con = C2hd = []; |
|
208 endif |
|
209 |
|
210 if(max(size(B2con)) & max(size(C2hd)) ) |
|
211 if(norm(B2con*C2hd)) |
|
212 warning("sysconnect: cont-state -> disc output -> cont state derivative"); |
|
213 warning(" connection made; resulting system may not be meaningful"); |
|
214 endif |
|
215 endif |
|
216 |
|
217 Ac = aa+B2*C2h; |
|
218 if(m1 > 0) |
|
219 B1c = B1 + B2*D21h; |
|
220 endif |
|
221 B2c = B2*(eye(size(D22h)) + D22h); |
|
222 if(p1*m1 > 0) |
|
223 D11c = D11 + D12*D21h; |
|
224 endif |
|
225 if(p1 > 0) |
|
226 C1c = C1+D12*C2h; |
|
227 D12c = D12*(eye(size(D22h))+D22h); |
|
228 endif |
|
229 |
|
230 ## construct system data structure |
|
231 if(m1 > 0) |
|
232 Bc = [B1c, B2c]; |
|
233 else |
|
234 Bc = B2c; |
|
235 endif |
|
236 |
|
237 if(p1 > 0) |
|
238 Cc = [C1c;C2h]; |
|
239 else |
|
240 Cc = C2h; |
|
241 endif |
|
242 |
|
243 if(m1*p1 > 0) |
|
244 Dc = [D11c,D12c; D21h,D22h]; |
|
245 elseif(m1 > 0) |
|
246 Dc = [D21h, D22h]; |
|
247 elseif(p1 > 0) |
|
248 Dc = [D12c; D22h]; |
|
249 else |
|
250 Dc = D22h; |
|
251 endif |
|
252 |
|
253 ## permute rows and columns of Bc, Cc, Dc back into original order |
|
254 Im = eye(mm,mm); |
|
255 Pi = Im(:,all_inputs); |
|
256 back_inputs = Pi*[1:mm]'; |
|
257 |
|
258 Ip = eye(pp,pp); |
|
259 Po = Ip(:,all_outputs); |
|
260 back_outputs = Po*[1:pp]'; |
|
261 |
|
262 Bc = Bc(:,back_inputs); |
|
263 Cc = Cc(back_outputs,:); |
|
264 Dc = Dc(back_outputs,back_inputs); |
|
265 yd = yd(back_outputs); |
|
266 |
|
267 ## rebuild system |
|
268 Ts = sysgettsam(sys); |
|
269 [stnam,innam,outnam] = sysgetsignals(sys); |
|
270 sys = ss2sys(Ac,Bc,Cc,Dc,Ts,nc,nz,stnam,innam,outnam,find(yd)); |
|
271 |
|
272 ## update connected input names |
|
273 for ii = 1:length(input_list) |
|
274 idx = input_list(ii); |
|
275 strval = sprintf("%s*",nth(sysgetsignals(sys,"in",idx),1) ); |
|
276 sys = syssetsignals(sys,"in",strval,idx); |
|
277 endfor |
|
278 |
|
279 ## maintain original system type if it was SISO |
|
280 if (strcmp (sysgettype (sys), "tf")) |
|
281 sysupdate (sys, "tf"); |
|
282 elseif (strcmp (sysgettype (sys),"zp")) |
|
283 sysupdate (sys, "zp"); |
|
284 endif |
|
285 |
|
286 endfunction |