Mercurial > hg > octave-nkf
view scripts/control/buildssic.m @ 3240:2e74d8aa1a20
[project @ 1999-04-07 18:33:23 by jwe]
author | jwe |
---|---|
date | Wed, 07 Apr 1999 18:34:20 +0000 |
parents | 041ea33fbbf4 |
children | 256f98d26275 |
line wrap: on
line source
# 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 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