Mercurial > octave-nkf
diff scripts/control/system/sysconnect.m @ 3430:65b3519ac3a1
[project @ 2000-01-14 03:44:03 by jwe]
author | jwe |
---|---|
date | Fri, 14 Jan 2000 03:50:02 +0000 |
parents | |
children | 04aef7306dca |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/control/system/sysconnect.m Fri Jan 14 03:50:02 2000 +0000 @@ -0,0 +1,277 @@ +## Copyright (C) 1996, 1998 Auburn University. All rights reserved. +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by the +## Free Software Foundation; either version 2, or (at your option) any +## later version. +## +## Octave is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, write to the Free +## Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{retsys} =} sysconnect (@var{sys}, @var{out_idx},@var{in_idx}@{,@var{order}, @var{tol}@}) +## Close the loop from specified outputs to respective specified inputs +## +## @strong{Inputs} +## @table @var +## @item sys +## system data structure +## @item out_idx +## @itemx in_idx +## list of connections indices; @math{y(out_idx(ii))} +## is connected to @math{u(in_idx(ii))}. +## @item order +## logical flag (default = 0) +## @table @code +## @item 0 +## leave inputs and outputs in their original order +## @item 1 +## permute inputs and outputs to the order shown in the diagram below +## @end table +## @item tol +## tolerance for singularities in algebraic loops default: 200@var{eps} +## @end table +## +## @strong{Outputs} +## @var{sys}: resulting closed loop system. +## +## @strong{Method} +## @code{sysconnect} internally permutes selected inputs, outputs as shown +## below, closes the loop, and then permutes inputs and outputs back to their +## original order +## @example +## @group +## ____________________ +## u_1 ----->| |----> y_1 +## | sys | +## old u_2 | | +## u_2* ---->(+)--->| |----->y_2 +## (in_idx) ^ -------------------| | (out_idx) +## | | +## ------------------------------- +## @end group +## @end example +## The input that has the summing junction added to it has an * added to +## the end of the input name. +## @end deftypefn + +## Author: A. S. Hodel <a.s.hodel@eng.auburn.edu> +## Created: August 1995 +## modified by John Ingram July 1996 + +function sys = sysconnect (sys, output_list, input_list, order, tol) + + if( (nargin < 3) | (nargin > 5) ) + usage("retsys = sysconnect(sys,output_list,input_list[,order,tol])"); + endif + + ## check order + if(nargin <= 3) + order = 0; + elseif( (order != 0) & (order != 1) ) + error("sysconnect: order must be either 0 or 1") + endif + + if (nargin <= 4) + tol = 200*eps; + elseif( !is_sample(tol) ) + error("sysconnect: tol must be a positive scalar"); + elseif(tol > 1e2*sqrt(eps)) + warning(["sysconnect: tol set to large value=",num2str(tol), ... + ", eps=",num2str(eps)]) + endif + + ## verify sizes,format of input, output lists + if( min(size(output_list))*min(size(input_list)) != 1) + error("output_list and input_list must be vectors"); + else + lo = length(output_list); + li = length(input_list); + if(lo != li) + error("output_list and input_list must be of the same length") + endif + + if(is_duplicate_entry(output_list) | is_duplicate_entry(input_list) ) + error("duplicate entry in input_list and/or output_list"); + endif + endif + + [nc,nz,mm,pp] = sysdimensions(sys); + nn = nc+nz; + + if( !is_struct(sys)) + error("sys must be in structured system form") + elseif(pp < li) + error(["length(output_list)=",num2str(li),", sys has only ", ... + num2str(pp),"system outputs"]) + elseif(mm < li) + error(["length(input_list)=",num2str(li),", sys has only ", ... + num2str(mm),"system inputs"]) + endif + + ## check that there are enough inputs/outputs in the system for the lists + if(max(input_list) > mm) + error("max(input_list) exceeds the number of inputs"); + elseif(max(output_list) > pp) + error("max(output_list) exceeds the number of outputs"); + endif + + output_list = reshape(output_list,1,length(output_list)); + + ## make sure we're in state space form + sys = sysupdate (sys, "ss"); + + ## permute rows and columns of B,C,D matrices into pseudo-dgkf form... + all_inputs = sysreorder(mm,input_list); + all_outputs = sysreorder(pp,output_list); + + [aa,bb,cc,dd] = sys2ss(sys); + bb = bb(:,all_inputs); + cc = cc(all_outputs,:); + dd = dd(all_outputs,all_inputs); + + yd = sysgetsignals(sys,"yd"); + yd = yd(all_outputs); + + ## m1, p1 = number of inputs, outputs that are not being connected + m1 = mm-li; + p1 = pp-li; + + ## m2, p2: 1st column, row of B, C that is being connected + m2 = m1+1; + p2 = p1+1; + + ## partition system into a DGKF-like form; the loop is closed around + ## B2, C2 + if(m1 > 0) + B1 = bb(:,1:m1); + D21= dd(p2:pp,1:m1); + endif + B2 = bb(:,m2:mm); + if(p1 > 0) + C1 = cc(1:p1,:); + D12= dd(1:p1,m2:mm); + endif + C2 = cc(p2:pp,:); + if(m1*p1 > 0) + D11= dd(1:p1,1:m1); + endif + D22= dd(p2:pp,m2:mm); + + if(norm(D22)) + warning("sysconnect: possible algebraic loop, D22 non-zero"); + D22i = (eye(size(D22))-D22); + C2h = D22i\C2; + if(m1 > 0) + D21h = D22i\D21; + endif + D22h = D22i\D22; + else + C2h = C2; + if(m1 > 0) + D21h = D21; + endif + D22h = D22; + + endif + + ## check cont state -> disc output -> cont state + dyi = find(yd(p2:pp)); + + ## disp("sysconnect: dyi=") + ## dyi + ## nc + ## disp("/sysconnect"); + + if( (nc > 0) & find(dyi > 0) ) + B2con = B2(1:nc,dyi); # connection to cont states + C2hd = C2h(dyi,1:nc); # cont states -> outputs + else + B2con = C2hd = []; + endif + + if(max(size(B2con)) & max(size(C2hd)) ) + if(norm(B2con*C2hd)) + warning("sysconnect: cont-state -> disc output -> cont state derivative"); + warning(" connection made; resulting system may not be meaningful"); + endif + endif + + Ac = aa+B2*C2h; + if(m1 > 0) + B1c = B1 + B2*D21h; + endif + B2c = B2*(eye(size(D22h)) + D22h); + if(p1*m1 > 0) + D11c = D11 + D12*D21h; + endif + if(p1 > 0) + C1c = C1+D12*C2h; + D12c = D12*(eye(size(D22h))+D22h); + endif + + ## construct system data structure + if(m1 > 0) + Bc = [B1c, B2c]; + else + Bc = B2c; + endif + + if(p1 > 0) + Cc = [C1c;C2h]; + else + Cc = C2h; + endif + + if(m1*p1 > 0) + Dc = [D11c,D12c; D21h,D22h]; + elseif(m1 > 0) + Dc = [D21h, D22h]; + elseif(p1 > 0) + Dc = [D12c; D22h]; + else + Dc = D22h; + endif + + ## permute rows and columns of Bc, Cc, Dc back into original order + Im = eye(mm,mm); + Pi = Im(:,all_inputs); + back_inputs = Pi*[1:mm]'; + + Ip = eye(pp,pp); + Po = Ip(:,all_outputs); + back_outputs = Po*[1:pp]'; + + Bc = Bc(:,back_inputs); + Cc = Cc(back_outputs,:); + Dc = Dc(back_outputs,back_inputs); + yd = yd(back_outputs); + + ## rebuild system + Ts = sysgettsam(sys); + [stnam,innam,outnam] = sysgetsignals(sys); + sys = ss2sys(Ac,Bc,Cc,Dc,Ts,nc,nz,stnam,innam,outnam,find(yd)); + + ## update connected input names + for ii = 1:length(input_list) + idx = input_list(ii); + strval = sprintf("%s*",nth(sysgetsignals(sys,"in",idx),1) ); + sys = syssetsignals(sys,"in",strval,idx); + endfor + + ## maintain original system type if it was SISO + if (strcmp (sysgettype (sys), "tf")) + sysupdate (sys, "tf"); + elseif (strcmp (sysgettype (sys),"zp")) + sysupdate (sys, "zp"); + endif + +endfunction