home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21eb.zip / octave / SCRIPTS.ZIP / scripts / control / sysconnect.m < prev    next >
Text File  |  1999-03-05  |  7KB  |  263 lines

  1. # Copyright (C) 1996,1998 A. Scottedward Hodel 
  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. # Octave is distributed in the hope that it will be useful, but WITHOUT 
  10. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  11. # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
  12. # for more details.
  13. # You should have received a copy of the GNU General Public License 
  14. # along with Octave; see the file COPYING.  If not, write to the Free 
  15. # Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  16.  
  17. function sys = sysconnect(sys,output_list,input_list,order,tol)
  18. # function retsys = sysconnect(sys,output_list,input_list[,order,tol])
  19. # Close the loop from specified outputs to respective specified inputs
  20. # inputs:
  21. #   sys: system data structure
  22. #   output_list,input_list: list of connections indices; y(output_list(ii))
  23. #       is connected to u(input_list(ii)).
  24. #   order: logical flag (default = 0)
  25. #    0: leave inputs and outputs in their original order
  26. #    1: permute inputs and outputs to the order shown in the diagram below
  27. #     tol: tolerance for singularities in algebraic loops
  28. #        default: 200*eps
  29. # output: sys: resulting closed loop system:
  30. #
  31. # Operation: sysconnect internally permutes selected inputs, outputs as shown
  32. # below, closes the loop, and then permutes inputs and outputs back to their
  33. # original order
  34. #                      ____________________
  35. #                      |                  |
  36. #    u_1         ----->|                  |----> y_1
  37. #                      |        sys       |
  38. #              old u_2 |                  |
  39. #   u_2* ------>(+)--->|                  |----->y_2 
  40. #   (input_list) ^     |                  |    | (output_list)
  41. #                |     --------------------    |
  42. #                |                             |
  43. #                -------------------------------
  44. #
  45. # The input that has the summing junction added to it has an * added to the end 
  46. # of the input name.
  47.  
  48. # A. S. Hodel August 1995
  49. # modified by John Ingram July 1996
  50.  
  51.   save_val = implicit_str_to_num_ok;    # save for later
  52.   implicit_str_to_num_ok = 1;
  53.  
  54.   if( (nargin < 3) | (nargin > 5) )
  55.     usage("retsys = sysconnect(sys,output_list,input_list[,order,tol])");
  56.   endif
  57.  
  58.   # check order
  59.   if(nargin <= 3)
  60.     order = 0;
  61.   elseif( (order != 0) & (order != 1) )
  62.     error("sysconnect: order must be either 0 or 1")
  63.   endif
  64.  
  65.   if (nargin <= 4)
  66.     tol = 200*eps;
  67.   elseif( !is_sample(tol) )
  68.     error("sysconnect: tol must be a positive scalar");
  69.   elseif(tol > 1e2*sqrt(eps))
  70.     warning(["sysconnect: tol set to large value=",num2str(tol), ...
  71.     ", eps=",num2str(eps)])
  72.   endif
  73.  
  74.   # verify sizes,format of input, output lists
  75.   if( min(size(output_list))*min(size(input_list)) != 1)
  76.     error("output_list and input_list must be vectors");
  77.   else
  78.     lo = length(output_list);
  79.     li = length(input_list);
  80.     if(lo != li)
  81.       error("output_list and input_list must be of the same length")
  82.     endif
  83.     
  84.     if(is_duplicate_entry(output_list) | is_duplicate_entry(input_list) )
  85.       error("duplicate entry in input_list and/or output_list");
  86.     endif
  87.   endif
  88.   
  89.   [nc,nz,mm,pp] = sysdimensions(sys);
  90.   nn = nc+nz;
  91.  
  92.   if( !is_struct(sys))
  93.     error("sys must be in structured system form")
  94.   elseif(pp < li)
  95.     error(["length(output_list)=",num2str(li),", sys has only ", ...
  96.     num2str(pp),"system outputs"])
  97.   elseif(mm < li)
  98.     error(["length(input_list)=",num2str(li),", sys has only ", ...
  99.     num2str(mm),"system inputs"])
  100.   endif
  101.  
  102.   # check that there are enough inputs/outputs in the system for the lists
  103.   if(max(input_list) > mm) 
  104.     error("max(input_list) exceeds the number of inputs");
  105.   elseif(max(output_list) > pp)
  106.     error("max(output_list) exceeds the number of outputs");
  107.   endif
  108.  
  109.   output_list = reshape(output_list,1,length(output_list));
  110.  
  111.   # make sure we're in state space form
  112.   sys = sysupdate(sys,'ss');
  113.  
  114.   # permute rows and columns of B,C,D matrices into pseudo-dgkf form...
  115.   all_inputs = sysreorder(mm,input_list);
  116.   all_outputs = sysreorder(pp,output_list);
  117.  
  118.   [aa,bb,cc,dd] = sys2ss(sys);
  119.   bb = bb(:,all_inputs);
  120.   cc = cc(all_outputs,:);
  121.   dd = dd(all_outputs,all_inputs);
  122.  
  123.   yd = sysgetsignals(sys,"yd");
  124.   yd = yd(all_outputs);
  125.  
  126.   # m1, p1 = number of inputs, outputs that are not being connected
  127.   m1 = mm-li;
  128.   p1 = pp-li;
  129.  
  130.   # m2, p2: 1st column, row of B, C that is being connected
  131.   m2 = m1+1;
  132.   p2 = p1+1;
  133.  
  134.   # partition system into a DGKF-like form; the loop is closed around
  135.   # B2, C2
  136.   if(m1 > 0)
  137.     B1 = bb(:,1:m1);
  138.     D21= dd(p2:pp,1:m1);
  139.   endif
  140.   B2 = bb(:,m2:mm);
  141.   if(p1 > 0)
  142.     C1 = cc(1:p1,:);
  143.     D12= dd(1:p1,m2:mm);
  144.   endif
  145.   C2 = cc(p2:pp,:);
  146.   if(m1*p1 > 0)
  147.     D11= dd(1:p1,1:m1);
  148.   endif
  149.   D22= dd(p2:pp,m2:mm);
  150.  
  151.   if(norm(D22))
  152.     warning("sysconnect: possible algebraic loop, D22 non-zero");
  153.     D22i = (eye(size(D22))-D22);
  154.     C2h = D22i\C2;
  155.     if(m1 > 0)
  156.       D21h = D22i\D21;
  157.     endif
  158.     D22h = D22i\D22;
  159.   else
  160.     C2h = C2;
  161.     if(m1 > 0)
  162.       D21h = D21;
  163.     endif
  164.     D22h = D22;
  165.  
  166.   endif
  167.  
  168.   # check cont state -> disc output -> cont state
  169.   dyi = find(yd(p2:pp));
  170.  
  171.   #disp("sysconnect: dyi=")
  172.   #dyi
  173.   #nc
  174.   #disp("/sysconnect");
  175.  
  176.   if( (nc > 0) & find(dyi > 0) )
  177.     B2con = B2(1:nc,dyi);    # connection to cont states
  178.     C2hd = C2h(dyi,1:nc);    # cont states -> outputs
  179.   else
  180.     B2con = C2hd = [];
  181.   endif
  182.  
  183.   if(max(size(B2con)) & max(size(C2hd)) )
  184.     if(norm(B2con*C2hd))
  185.       warning("sysconnect: cont-state -> disc output -> cont state derivative");
  186.       warning("    connection made; resulting system may not be meaningful");
  187.     endif
  188.   endif
  189.  
  190.   Ac = aa+B2*C2h;
  191.   if(m1 > 0)
  192.     B1c = B1 + B2*D21h;
  193.   endif
  194.   B2c = B2*(eye(size(D22h)) + D22h);
  195.   if(p1*m1 > 0)
  196.     D11c = D11 + D12*D21h;
  197.   endif
  198.   if(p1 > 0)
  199.     C1c  = C1+D12*C2h;
  200.     D12c = D12*(eye(size(D22h))+D22h);
  201.   endif
  202.  
  203.   # construct system data structure
  204.   if(m1 > 0)
  205.    Bc = [B1c, B2c];
  206.   else
  207.    Bc = B2c;
  208.   endif
  209.  
  210.   if(p1 > 0)
  211.     Cc = [C1c;C2h];
  212.   else
  213.     Cc = C2h;
  214.   endif
  215.  
  216.   if(m1*p1 > 0)
  217.     Dc = [D11c,D12c; D21h,D22h];
  218.   elseif(m1 > 0)
  219.     Dc = [D21h, D22h];
  220.   elseif(p1 > 0)
  221.     Dc = [D12c; D22h];
  222.   else
  223.     Dc = D22h;
  224.   endif 
  225.  
  226.   # permute rows and columns of Bc, Cc, Dc back into original order
  227.   Im = eye(mm,mm);
  228.   Pi = Im(:,all_inputs);
  229.   back_inputs = Pi*[1:mm]';
  230.  
  231.   Ip = eye(pp,pp);
  232.   Po = Ip(:,all_outputs);
  233.   back_outputs = Po*[1:pp]';
  234.  
  235.   Bc = Bc(:,back_inputs);
  236.   Cc = Cc(back_outputs,:);
  237.   Dc = Dc(back_outputs,back_inputs);
  238.   yd = yd(back_outputs);
  239.  
  240.   # rebuild system
  241.   Ts = sysgettsam(sys);
  242.   [stnam,innam,outnam] = sysgetsignals(sys);
  243.   sys = ss2sys(Ac,Bc,Cc,Dc,Ts,nc,nz,stnam,innam,outnam,find(yd));
  244.  
  245.   # update connected input names
  246.   for ii = 1:length(input_list)
  247.     idx = input_list(ii);
  248.     strval = sprintf("%s*",nth(sysgetsignals(sys,"in",idx),1) );
  249.     sys = syssetsignals(sys,"in",strval,idx);
  250.   endfor
  251.   
  252.   # maintain original system type if it was SISO
  253.   if    (strcmp(sysgettype(sys),"tf") )       sysupdate(sys,'tf');
  254.   elseif(strcmp(sysgettype(sys),"zp") )       sysupdate(sys,'zp');
  255.   endif
  256.  
  257.   implicit_str_to_num_ok = save_val;    # restore value  
  258.  
  259. endfunction
  260.