1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
|
## Copyright (C) 1998, 2000, 2002, 2004, 2005, 2006, 2007
## Auburn University. All rights reserved.
##
##
## This program 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 3 of the License, or (at
## your option) any later version.
##
## This program 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 this program; see the file COPYING. If not, see
## <http://www.gnu.org/licenses/>.
## -*- texinfo -*-
## @deftypefn {Function File} {[@var{dsys}, @var{fidx}] =} dmr2d (@var{sys}, @var{idx}, @var{sprefix}, @var{ts2}, @var{cuflg})
## convert a multirate digital system to a single rate digital system
## states specified by @var{idx}, @var{sprefix} are sampled at @var{ts2}, all
## others are assumed sampled at @var{ts1} = @code{sysgettsam (@var{sys})}.
##
## @strong{Inputs}
## @table @var
## @item sys
## discrete time system;
## @code{dmr2d} exits with an error if @var{sys} is not discrete
## @item idx
## indices or names of states with sampling time
## @code{sysgettsam(@var{sys})} (may be empty); see @code{cellidx}
## @item sprefix
## list of string prefixes of states with sampling time
## @code{sysgettsam(@var{sys})} (may be empty)
## @item ts2
## sampling time of states not specified by @var{idx}, @var{sprefix}
## must be an integer multiple of @code{sysgettsam(@var{sys})}
## @item cuflg
## "constant u flag" if @var{cuflg} is nonzero then the system inputs are
## assumed to be constant over the revised sampling interval @var{ts2}.
## Otherwise, since the inputs can change during the interval
## @var{t} in @math{[k ts2, (k+1) ts2]}, an additional set of inputs is
## included in the revised B matrix so that these intersample inputs
## may be included in the single-rate system.
## default @var{cuflg} = 1.
## @end table
##
## @strong{Outputs}
## @table @var
## @item dsys
## equivalent discrete time system with sampling time @var{ts2}.
##
## The sampling time of sys is updated to @var{ts2}.
##
## if @var{cuflg}=0 then a set of additional inputs is added to
## the system with suffixes _d1, @dots{}, _dn to indicate their
## delay from the starting time k @var{ts2}, i.e.
## u = [u_1; u_1_d1; @dots{}, u_1_dn] where u_1_dk is the input
## k*ts1 units of time after u_1 is sampled. (@var{ts1} is
## the original sampling time of the discrete time system and
## @var{ts2} = (n+1)*ts1)
##
## @item fidx
## indices of "formerly fast" states specified by @var{idx} and @var{sprefix};
## these states are updated to the new (slower) sampling interval @var{ts2}.
## @end table
##
## @strong{WARNING} Not thoroughly tested yet; especially when
## @var{cuflg} == 0.
## @end deftypefn
## Adapted from c2d by a.s.hodel@eng.auburn.edu
function [dsys, fidx] = dmr2d (sys, idx, sprefix, Ts2, cuflg)
## parse input arguments
if (nargin != 4)
print_usage ();
elseif (! isstruct (sys))
error ("sys must be in system data structure form");
elseif (! is_digital (sys))
error ("sys must be discrete-time; continuous time passed");
endif
if (is_signal_list (idx) || ischar (idx))
idx = sysidx (sys, "st", idx);
elseif (! (isvector (idx) || isempty (idx)))
error ("idx(%dx%d) must be a vector", rows (idx), columns (idx));
elseif (any (idx <= 0))
idv = find (idx <= 0);
ii = idv(1);
error ("idx(%d)=%g; entries of idx must be positive", ii, idx(ii));
elseif (! (is_signal_list (sprefix) || isempty (sprefix)))
error ("sprefix must be a signal list (see is_signal_list) or empty");
elseif (! is_sample (Ts2))
error ("Ts2=%g; invalid sampling time", Ts2);
endif
## optional argument: cuflg
if (nargin <= 4)
cuflg = 1; # default: constant inputs over Ts2 sampling interv.
elseif (! isscalar (cuflg))
error ("cuflg must be a scalar")
elseif (cuflg != 0 || cuflg != 1)
error ("cuflg = %g, should be 0 or 1", cuflg);
endif
## extract state space information
[da, db, dc, dd, Ts1, nc, nz, stname, inname, outname, yd] = sys2ss (sys);
## compute number of steps
if (Ts1 > Ts2)
error ("Current sampling time=%g > Ts2=%g", Ts1, Ts2);
endif
nstp = floor (Ts2/Ts1+0.5);
if (abs ((Ts2 - Ts1*nstp)/Ts1) > 1e-12)
warning ("dmr2d: Ts1=%g, Ts2=%g, selecting nsteps=%d; mismatch",
Ts1, Ts2, nstp);
endif
if (isempty (sprefix) && isempty (idx))
warning ("both sprefix and idx are empty; returning dsys=sys");
fidx = [];
dsys = sys;
return
elseif (isempty (sprefix))
fidx = idx;
else
fidx = reshape (idx, 1, length(idx));
## find states whose name begins with any strings in sprefix.
ns = length (sprefix);
for kk = 1:ns
spk = sprefix{kk}; # get next prefix and length
spl = length (spk);
## check each state name
for ii = 1:nz
sti = stname{ii}; # compare spk with this state name
if (length (sti) >= spl)
## if the prefix matches and ii isn't already in the list, add ii
if (strcmp (sti(1:spl), spk) && ! any (fidx == ii))
fidx = sort ([fidx, ii]);
endif
endif
endfor
endfor
endif
if (nstp == 0)
warning ("dmr2d: nstp = 0; setting tsam and returning");
dsys = syschtsam (sys, Ts2);
return;
elseif (nstp < 0)
error ("nstp = %d < 0; this shouldn't be!", nstp);
endif
## permute system matrices
pv = sysreorder (nz, fidx);
pv = pv(nz:-1:1); # reverse order to put fast modes in leading block
## construct inverse permutation
Inz = eye (nz);
pvi = (Inz(pv,:)'*[1:nz]')';
## permute A, B (stname permuted for debugging only)
da = da(pv,pv);
db = db(pv,:);
stname = stname (pv);
## partition A, B:
lfidx = length (fidx);
bki = 1:lfidx;
a11 = da(bki,bki);
b1 = db(bki,:);
if (lfidx < nz)
lfidx1 = lfidx+1;
bki2 = (lfidx1):nz;
a12 = da(bki,bki2);
b2 = db(bki2,:);
else
warning ("dmr2d: converting entire A,B matrices to new sampling rate");
lfidx1 = -1;
bki2 = [];
endif
## begin system conversion: nstp steps
## compute abar_{n-1}*a12 and appropriate b matrix stuff
a12b = a12; # running total of abar_{n-1}*a12
a12w = a12; # current a11^n*a12 (start with n = 0)
if (cuflg)
b1b = b1;
b1w = b1;
else
## cuflg == 0, need to keep track of intersample inputs too
## FIXME: check tolerance relative to ||b1||
nzdx = find (max (abs (b1)) != 0);
b1w = b1(nzdx);
innamenz = inname(nzdx);
b1b = b1; # initial b1 must match columns in b2
endif
## compute a11h = a11^nstp by squaring
a11h = eye (size (a11));
p2 = 1;
a11p2 = a11; #a11^p2
nstpw = nstp; # workspace for computing a11^nstp
while (nstpw > 0.5)
oddv = rem (nstpw, 2);
if (oddv)
a11h = a11h*a11p2;
endif
nstpw = (nstpw-oddv)/2;
if (nstpw > 0.5)
a11p2 = a11p2*a11p2; # a11^(next power of 2)
endif
endwhile
## FIXME: this part should probably also use squaring, but
## that would require exponentially growing memory. What do do?
for kk = 2:nstp
## update a12 block to sum(a12 + ... + a11^(kk-1)*a12)
a12w = a11*a12w;
a12b = a12b + a12w;
## similar for b1 block (checking for cuflg first!)
b1w = a11*b1w;
if (cuflg)
b1b = b1b + b1w; # update b1 block just like we did a12
else
b1b = [b1b, b1w]; # append new inputs
newin = sprintf ("%s_d%d", innamenz, kk-1);
inname = __sysconcat__ (inname, newin);
endif
endfor
## reconstruct system and return
da(bki,bki) = a11h;
db(bki,1:columns(b1b)) = b1b;
if (! isempty (bki2))
da(bki,bki2) = a12b;
endif
da = da(pvi,pvi);
db = db(pvi,:);
stname = stname(pvi);
## construct new system and return
dsys = ss (da, db, dc, dd, Ts2, 0, nz, stname, inname, outname,
find (yd == 1));
endfunction
|