diff scripts/control/buildssic.m @ 3213:ba1c7cdc6090

[project @ 1998-11-06 16:15:36 by jwe]
author jwe
date Fri, 06 Nov 1998 16:16:31 +0000
parents
children dbcc24961c44
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/scripts/control/buildssic.m
@@ -0,0 +1,299 @@
+# Copyright (C) 1998 Kai P. Mueller
+#
+# 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, 675 Mass Ave, Cambridge, MA 02139, USA. 
+ 
+function [sys] = buildssic(Clst,Ulst,Olst,Ilst,s1,s2,s3,s4,s5,s6,s7,s8)
+#
+# [sys] = buildssic(Clst,Ulst,Olst,Ilst,s1,s2,s3,s4,s5,s6,s7,s8)
+#
+# Form an arbitrary complex (open or closed loop) system in
+# state-space form from several systems. "buildssic" can
+# easily (despite it's cryptic syntax) integrate transfer functions
+# from a complex block diagram into a single system with one call.
+# This function is especially useful for building open loop
+# interconnections for H_infinity and H2 designs or for closing
+# loops with these controllers.
+#
+# Although this function is general purpose, the use of "sysgroup"
+# "sysmult", "sysconnect" and the like ist recommended for standard
+# operations since they can handle mixed discrete and continuous
+# systems and also the names of inputs, outputs, and states.
+# 
+# The parameters consist of 4 lists which describe the connections
+# outputs and inputs and up to 8 systems s1-s8.
+# Format of the lists:
+#
+#     Clst: connection list, describes the input signal of
+#           each system. The maximum number of rows of Clst is
+#           equal to the sum of all inputs of s1-s8.
+#           Example:
+#             [1 2 -1; 2 1 0] ==> new input 1 is old inpout 1
+#             + output 2 - output 1, new input 2 is old input 2
+#             + output 1. The order of rows is arbitrary.
+#
+#     Ulst: if not empty the old inputs in vector Ulst will
+#           be appended to the outputs. You need this if you
+#           want to "pull out" the input of a system. Elements
+#           are input numbers of s1-s8.
+#
+#     Olst: output list, specifiy the outputs of the resulting
+#           systems. Elements are output numbers of s1-s8.
+#           The numbers are alowed to be negative and may
+#           appear in any order. An empty matrix means
+#           all outputs.
+#
+#     Ilst: input list, specifiy the inputs of the resulting
+#           systems. Elements are input numbers of s1-s8.
+#           The numbers are alowed to be negative and may
+#           appear in any order. An empty matrix means
+#           all inputs.
+#
+# Example:  Very simple closed loop system.
+#
+#       w        e  +-----+   u  +-----+
+#        --->o--*-->|  K  |--*-->|  G  |--*---> y
+#            ^  |   +-----+  |   +-----+  |
+#          - |  |            |            |
+#            |  |            +----------------> u
+#            |  |                         |
+#            |  +-------------------------|---> e
+#            |                            |
+#            +----------------------------+
+#
+# The closed loop system GW can be optained by
+#
+#     GW = buildssic([1 2; 2 -1], [2], [1 2 3], [2], G, K);
+#
+# Clst: (1. row) connect input 1 (G) with output 2 (K).
+#       (2. row) connect input 2 (K) with neg. output 1 (G).
+# Ulst: append input of (2) K to the number of outputs.
+# Olst: Outputs are output of 1 (G), 2 (K) and appended
+#       output 3 (from Ulst).
+# Ilst: the only input is 2 (K).
+#
+# Here is a real example:
+#	                         +----+
+#	    -------------------->| W1 |---> v1
+#	z   |                    +----+
+#	----|-------------+                   || GW   ||     => min.
+#	    |             |                        vz   infty
+#	    |    +---+    v      +----+
+#	    *--->| G |--->O--*-->| W2 |---> v2
+#	    |    +---+       |   +----+
+#	    |                |
+#           |                v
+#          u                  y
+#
+# The closed loop system GW from [z; u]' to [v1; v2; y]' can be
+# obtained by (all SISO systems):
+#
+#     GW = buildssic([1 4;2 4;3 1],[3],[2 3 5],[3 4],G,W1,W2,One);
+#
+# where "One" is a unity gain (auxillary) function with order 0.
+# (e.g. One = ugain(1);)
+#
+
+# Written by Kai Mueller April 1998
+# $Revision: 1.2 $
+# $Log: buildssic.m,v $
+# Revision 1.2  1998/10/12  10:04:14  mueller
+# bugfix: build of discrete systems corrected.
+# The previous version did not sum up the discrete states.
+#
+# Revision 1.1  1998/10/12  08:51:49  mueller
+# Initial revision
+#
+# Revision 1.1.1.1  1998/05/19 20:24:05  jwe
+#
+# Revision 1.1  1998/05/05 17:02:56  scotte
+# Initial revision
+#
+# Revision 1.2  1998/05/05  08:19:59  mueller
+# minor corrections
+#
+# Revision 1.1  1998/05/04  15:09:32  mueller
+# Initial revision
+#
+
+  if((nargin < 5) || (nargin > 12))
+    usage("[sys] = buildssic(Clst,Ulst,Olst,Ilst,s1,s2,s3,s4,s5,s6,s7,s8)");
+  endif
+  if (nargin >= 5)
+    if (!is_struct(s1))
+      error("---> s1 must be a structed system.");
+    endif
+    s1 = sysupdate(s1, "ss");
+    [n, nz, m, p] = sysdimensions(s1);
+    if (!n && !nz)
+      error("---> pure static system must not be the first in list.");
+    endif
+    if (n && nz)
+      error("---> cannot handle mixed continuous and discrete systems.");
+    endif
+    D_SYS = (nz > 0);
+    [A,B,C,D,tsam] = sys2ss(s1);
+    nt = n + nz;
+  endif
+  for ii = 6:nargin
+    eval(["ss = s" num2str(ii-4) ";"]);
+    if (!is_struct(ss))
+      error("---> Parameter must be a structed system.");
+    endif
+    ss = sysupdate(ss, "ss");
+    [n1, nz1, m1, p1] = sysdimensions(ss);
+    if (n1 && nz1)
+      error("---> cannot handle mixed continuous and discrete systems.");
+    endif
+    if (D_SYS)
+      if (n1)
+      	error("---> cannot handle mixed cont. and discr. systems.");
+      endif
+      if (tsam != sysgettsam(ss))
+	error("---> sampling time of all systems must match.");
+      endif
+    endif
+    [as,bs,cs,ds] = sys2ss(ss);
+    nt1 = n1 + nz1;
+    if (!nt1)
+      # pure gain (pad B, C with zeros)
+      B = [B  zeros(nt,m1)];
+      C = [C; zeros(p1,nt)];
+    else
+      A = [A  zeros(nt,nt1); zeros(nt1,nt) as];
+      B = [B  zeros(nt,m1);  zeros(nt1,m)  bs];
+      C = [C  zeros(p,nt1);  zeros(p1,nt)  cs];
+    endif
+    D = [D  zeros(p,m1); zeros(p1,m) ds];
+    n = n + n1;
+    nz = nz + nz1;
+    nt = nt + nt1;
+    m = m + m1;
+    p = p + p1;
+  endfor
+
+  # check maximum dimensions
+  [nx, mx] = size(Clst);
+  if (nx > m)
+    error("---> more rows in Clst than total number of inputs.");
+  endif
+  if (mx > p+1)
+    error("---> more cols in Clst than total number of outputs.");
+  endif
+  # empty vector Ulst is OK
+  lul = length(Ulst);
+  if (lul)
+    if (!is_vector(Ulst))
+      error("---> Input u list Ulst must be a vector.");
+    endif
+    if (lul > m)
+      error("---> more values in Ulst than number of inputs.");
+    endif
+  endif
+  if (!length(Olst))  Olst = [1:(p+lul)];  endif
+  if (!length(Ilst))  Ilst = [1:m];        endif
+  if (!is_vector(Olst))
+    error("---> Output list Olst must be a vector.");
+  endif
+  if (!is_vector(Ilst))
+    error("---> Input list Ilst must be a vector.");
+  endif
+
+  # build the feedback "K" from the interconnection data Clst
+  K = zeros(m, p);
+  inp_used = zeros(m,1);
+  for ii = 1:nx
+    xx = Clst(ii,:);
+    iu = xx(1);
+    if ((iu < 1) || (iu > m))
+      error("---> Illegal value in first col of Clst.");
+    endif
+    if (inp_used(iu))
+      error("---> Input specified more than once.");
+    endif
+    inp_used(iu) = 1;
+    for kk = 2:mx
+      it = xx(kk);
+      if (abs(it) > p)
+      	error("---> Illegal row value in Clst.");
+      elseif (it)
+	K(iu,abs(it)) = sign(it);
+      endif
+    endfor
+  endfor
+
+  # form the "closed loop", i.e replace u in
+  # .
+  # x = Ax + Bu
+  #                            ~
+  # y = Cx + Du   by   u = K*y+u
+  #
+  #            -1
+  # R = (I-D*K)   must exist.
+  # 
+  R = eye(p) - D*K;
+  if (rank(R) < m)
+    error("---> singularity in algebraic loop.");
+  else
+    R = inv(R);
+  endif
+  A = A + B*K*R*C;
+  B = B + B*K*R*D;
+  C = R*C;
+  D = R*D;
+
+  # append old inputs u to the outputs (if lul > 0)
+  kc = K*C;
+  kdi = eye(m) + K*D;
+  for ii = 1:lul
+    it = Ulst(ii);
+    if ((it < 1) || (it > m))
+      error("---> Illegal value in Ulst.");
+    endif
+    C = [C; kc(it,:)];
+    D = [D; kdi(it,:)];
+  endfor
+
+  # select and rearrange outputs
+  nn = length(A);
+  lol = length(Olst);
+  Cnew = zeros(lol,nn);
+  Dnew = zeros(lol,m);
+  for ii = 1:lol
+    iu = Olst(ii);
+    if (!iu || (abs(iu) > p+lul))
+      error("---> Illegal value in Olst.");
+    endif
+    Cnew(ii,:) = sign(iu)*C(abs(iu),:);
+    Dnew(ii,:) = sign(iu)*D(abs(iu),:);
+  endfor
+  C = Cnew;
+  D = Dnew;
+  lil = length(Ilst);
+  Bnew = zeros(nn,lil);
+  Dnew = zeros(lol,lil);
+  for ii = 1:lil
+    iu = Ilst(ii);
+    if (!iu || (abs(iu) > m))
+      error("---> Illegal value in Ilst.");
+    endif
+    Bnew(:,ii) = sign(iu)*B(:,abs(iu));
+    Dnew(:,ii) = sign(iu)*D(:,abs(iu));
+  endfor
+
+  sys = ss2sys(A, Bnew, C, Dnew, tsam, n, nz);
+
+endfunction