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

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