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

  1. # Copyright (C) 1998 Kai P. Mueller
  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] = buildssic(Clst,Ulst,Olst,Ilst,s1,s2,s3,s4,s5,s6,s7,s8)
  18. #
  19. # [sys] = buildssic(Clst,Ulst,Olst,Ilst,s1,s2,s3,s4,s5,s6,s7,s8)
  20. #
  21. # Form an arbitrary complex (open or closed loop) system in
  22. # state-space form from several systems. "buildssic" can
  23. # easily (despite it's cryptic syntax) integrate transfer functions
  24. # from a complex block diagram into a single system with one call.
  25. # This function is especially useful for building open loop
  26. # interconnections for H_infinity and H2 designs or for closing
  27. # loops with these controllers.
  28. #
  29. # Although this function is general purpose, the use of "sysgroup"
  30. # "sysmult", "sysconnect" and the like ist recommended for standard
  31. # operations since they can handle mixed discrete and continuous
  32. # systems and also the names of inputs, outputs, and states.
  33. # The parameters consist of 4 lists which describe the connections
  34. # outputs and inputs and up to 8 systems s1-s8.
  35. # Format of the lists:
  36. #
  37. #     Clst: connection list, describes the input signal of
  38. #           each system. The maximum number of rows of Clst is
  39. #           equal to the sum of all inputs of s1-s8.
  40. #           Example:
  41. #             [1 2 -1; 2 1 0] ==> new input 1 is old inpout 1
  42. #             + output 2 - output 1, new input 2 is old input 2
  43. #             + output 1. The order of rows is arbitrary.
  44. #
  45. #     Ulst: if not empty the old inputs in vector Ulst will
  46. #           be appended to the outputs. You need this if you
  47. #           want to "pull out" the input of a system. Elements
  48. #           are input numbers of s1-s8.
  49. #
  50. #     Olst: output list, specifiy the outputs of the resulting
  51. #           systems. Elements are output numbers of s1-s8.
  52. #           The numbers are alowed to be negative and may
  53. #           appear in any order. An empty matrix means
  54. #           all outputs.
  55. #
  56. #     Ilst: input list, specifiy the inputs of the resulting
  57. #           systems. Elements are input numbers of s1-s8.
  58. #           The numbers are alowed to be negative and may
  59. #           appear in any order. An empty matrix means
  60. #           all inputs.
  61. #
  62. # Example:  Very simple closed loop system.
  63. #
  64. #       w        e  +-----+   u  +-----+
  65. #        --->o--*-->|  K  |--*-->|  G  |--*---> y
  66. #            ^  |   +-----+  |   +-----+  |
  67. #          - |  |            |            |
  68. #            |  |            +----------------> u
  69. #            |  |                         |
  70. #            |  +-------------------------|---> e
  71. #            |                            |
  72. #            +----------------------------+
  73. #
  74. # The closed loop system GW can be optained by
  75. #
  76. #     GW = buildssic([1 2; 2 -1], [2], [1 2 3], [2], G, K);
  77. #
  78. # Clst: (1. row) connect input 1 (G) with output 2 (K).
  79. #       (2. row) connect input 2 (K) with neg. output 1 (G).
  80. # Ulst: append input of (2) K to the number of outputs.
  81. # Olst: Outputs are output of 1 (G), 2 (K) and appended
  82. #       output 3 (from Ulst).
  83. # Ilst: the only input is 2 (K).
  84. #
  85. # Here is a real example:
  86. #                             +----+
  87. #        -------------------->| W1 |---> v1
  88. #    z   |                    +----+
  89. #    ----|-------------+                   || GW   ||     => min.
  90. #        |             |                        vz   infty
  91. #        |    +---+    v      +----+
  92. #        *--->| G |--->O--*-->| W2 |---> v2
  93. #        |    +---+       |   +----+
  94. #        |                |
  95. #           |                v
  96. #          u                  y
  97. #
  98. # The closed loop system GW from [z; u]' to [v1; v2; y]' can be
  99. # obtained by (all SISO systems):
  100. #
  101. #     GW = buildssic([1 4;2 4;3 1],[3],[2 3 5],[3 4],G,W1,W2,One);
  102. #
  103. # where "One" is a unity gain (auxillary) function with order 0.
  104. # (e.g. One = ugain(1);)
  105. #
  106.  
  107. # Written by Kai Mueller April 1998
  108.  
  109.   if((nargin < 5) || (nargin > 12))
  110.     usage("[sys] = buildssic(Clst,Ulst,Olst,Ilst,s1,s2,s3,s4,s5,s6,s7,s8)");
  111.   endif
  112.   if (nargin >= 5)
  113.     if (!is_struct(s1))
  114.       error("---> s1 must be a structed system.");
  115.     endif
  116.     s1 = sysupdate(s1, "ss");
  117.     [n, nz, m, p] = sysdimensions(s1);
  118.     if (!n && !nz)
  119.       error("---> pure static system must not be the first in list.");
  120.     endif
  121.     if (n && nz)
  122.       error("---> cannot handle mixed continuous and discrete systems.");
  123.     endif
  124.     D_SYS = (nz > 0);
  125.     [A,B,C,D,tsam] = sys2ss(s1);
  126.     nt = n + nz;
  127.   endif
  128.   for ii = 6:nargin
  129.     eval(["ss = s", num2str(ii-4), ";"]);
  130.     if (!is_struct(ss))
  131.       error("---> Parameter must be a structed system.");
  132.     endif
  133.     ss = sysupdate(ss, "ss");
  134.     [n1, nz1, m1, p1] = sysdimensions(ss);
  135.     if (n1 && nz1)
  136.       error("---> cannot handle mixed continuous and discrete systems.");
  137.     endif
  138.     if (D_SYS)
  139.       if (n1)
  140.           error("---> cannot handle mixed cont. and discr. systems.");
  141.       endif
  142.       if (tsam != sysgettsam(ss))
  143.     error("---> sampling time of all systems must match.");
  144.       endif
  145.     endif
  146.     [as,bs,cs,ds] = sys2ss(ss);
  147.     nt1 = n1 + nz1;
  148.     if (!nt1)
  149.       # pure gain (pad B, C with zeros)
  150.       B = [B, zeros(nt,m1)];
  151.       C = [C; zeros(p1,nt)];
  152.     else
  153.       A = [A, zeros(nt,nt1); zeros(nt1,nt), as];
  154.       B = [B, zeros(nt,m1);  zeros(nt1,m),  bs];
  155.       C = [C, zeros(p,nt1);  zeros(p1,nt),  cs];
  156.     endif
  157.     D = [D, zeros(p,m1); zeros(p1,m), ds];
  158.     n = n + n1;
  159.     nz = nz + nz1;
  160.     nt = nt + nt1;
  161.     m = m + m1;
  162.     p = p + p1;
  163.   endfor
  164.  
  165.   # check maximum dimensions
  166.   [nx, mx] = size(Clst);
  167.   if (nx > m)
  168.     error("---> more rows in Clst than total number of inputs.");
  169.   endif
  170.   if (mx > p+1)
  171.     error("---> more cols in Clst than total number of outputs.");
  172.   endif
  173.   # empty vector Ulst is OK
  174.   lul = length(Ulst);
  175.   if (lul)
  176.     if (!is_vector(Ulst))
  177.       error("---> Input u list Ulst must be a vector.");
  178.     endif
  179.     if (lul > m)
  180.       error("---> more values in Ulst than number of inputs.");
  181.     endif
  182.   endif
  183.   if (!length(Olst))  Olst = [1:(p+lul)];  endif
  184.   if (!length(Ilst))  Ilst = [1:m];        endif
  185.   if (!is_vector(Olst))
  186.     error("---> Output list Olst must be a vector.");
  187.   endif
  188.   if (!is_vector(Ilst))
  189.     error("---> Input list Ilst must be a vector.");
  190.   endif
  191.  
  192.   # build the feedback "K" from the interconnection data Clst
  193.   K = zeros(m, p);
  194.   inp_used = zeros(m,1);
  195.   for ii = 1:nx
  196.     xx = Clst(ii,:);
  197.     iu = xx(1);
  198.     if ((iu < 1) || (iu > m))
  199.       error("---> Illegal value in first col of Clst.");
  200.     endif
  201.     if (inp_used(iu))
  202.       error("---> Input specified more than once.");
  203.     endif
  204.     inp_used(iu) = 1;
  205.     for kk = 2:mx
  206.       it = xx(kk);
  207.       if (abs(it) > p)
  208.           error("---> Illegal row value in Clst.");
  209.       elseif (it)
  210.     K(iu,abs(it)) = sign(it);
  211.       endif
  212.     endfor
  213.   endfor
  214.  
  215.   # form the "closed loop", i.e replace u in
  216.   # .
  217.   # x = Ax + Bu
  218.   #                            ~
  219.   # y = Cx + Du   by   u = K*y+u
  220.   #
  221.   #            -1
  222.   # R = (I-D*K)   must exist.
  223.   # 
  224.   R = eye(p) - D*K;
  225.   if (rank(R) < m)
  226.     error("---> singularity in algebraic loop.");
  227.   else
  228.     R = inv(R);
  229.   endif
  230.   A = A + B*K*R*C;
  231.   B = B + B*K*R*D;
  232.   C = R*C;
  233.   D = R*D;
  234.  
  235.   # append old inputs u to the outputs (if lul > 0)
  236.   kc = K*C;
  237.   kdi = eye(m) + K*D;
  238.   for ii = 1:lul
  239.     it = Ulst(ii);
  240.     if ((it < 1) || (it > m))
  241.       error("---> Illegal value in Ulst.");
  242.     endif
  243.     C = [C; kc(it,:)];
  244.     D = [D; kdi(it,:)];
  245.   endfor
  246.  
  247.   # select and rearrange outputs
  248.   nn = length(A);
  249.   lol = length(Olst);
  250.   Cnew = zeros(lol,nn);
  251.   Dnew = zeros(lol,m);
  252.   for ii = 1:lol
  253.     iu = Olst(ii);
  254.     if (!iu || (abs(iu) > p+lul))
  255.       error("---> Illegal value in Olst.");
  256.     endif
  257.     Cnew(ii,:) = sign(iu)*C(abs(iu),:);
  258.     Dnew(ii,:) = sign(iu)*D(abs(iu),:);
  259.   endfor
  260.   C = Cnew;
  261.   D = Dnew;
  262.   lil = length(Ilst);
  263.   Bnew = zeros(nn,lil);
  264.   Dnew = zeros(lol,lil);
  265.   for ii = 1:lil
  266.     iu = Ilst(ii);
  267.     if (!iu || (abs(iu) > m))
  268.       error("---> Illegal value in Ilst.");
  269.     endif
  270.     Bnew(:,ii) = sign(iu)*B(:,abs(iu));
  271.     Dnew(:,ii) = sign(iu)*D(:,abs(iu));
  272.   endfor
  273.  
  274.   sys = ss2sys(A, Bnew, C, Dnew, tsam, n, nz);
  275.  
  276. endfunction
  277.