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

  1. # Copyright (C) 1996,1998 A. Scottedward Hodel 
  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 csys = d2c(sys,opt)
  18. # csys = d2c(sys[,tol])
  19. # csys = d2c(sys,opt)
  20. #
  21. # inputs: 
  22. #   sys: system data structure with discrete components
  23. #   tol: tolerance for convergence of default "log" option (see below)
  24. #
  25. #   opt: conversion option.  Choose from:
  26. #        "log":  (default) Conversion is performed via a matrix logarithm.
  27. #                Due to some problems with this computation, it is
  28. #                followed by a steepest descent to identify continuous time 
  29. #                A, B, to get a better fit to the original data.  
  30. #
  31. #                If called as d2c(sys,tol), tol=positive scalar, the log
  32. #                option is used.  The default value for tol is 1e-8.
  33. #        "bi": Conversion is performed via bilinear transform
  34. #                  1 + s T/2
  35. #              z = ---------
  36. #                  1 - s T/2
  37. #              where T is the system sampling time (see syschtsam).
  38. #
  39. #              FIXME: exits with an error if sys is not purely discrete
  40. #
  41. # D2C converts the real-coefficient discrete time state space system
  42. #
  43. #        x(k+1) = A x(k) + B u(k)
  44. #
  45. # to a continuous time state space system
  46. #        .
  47. #        x = A1 x + B1 u
  48. #
  49. # The sample time used is that of the system. (see syschtsam).
  50.   
  51. # Written by R. Bruce Tenison August 23, 1994
  52. # Updated by John Ingram for system data structure  August 1996
  53. # SYS_INTERNAL accesses members of system data structure
  54.  
  55.   save_val = implicit_str_to_num_ok;    # save for later
  56.   implicit_str_to_num_ok = 1;
  57.  
  58.   if( (nargin != 1) & (nargin != 2) )
  59.     usage("csys = d2c(sys[,tol]), csys = d2c(sys,opt)");
  60.   elseif (!is_struct(sys))
  61.     error("sys must be in system data structure");
  62.   elseif(nargin == 1)
  63.     opt = "log";
  64.     tol = 1e-12;
  65.   elseif(isstr(opt))   # all remaining cases are for nargin == 2
  66.     tol = 1e-12;
  67.     if( !(strcmp(opt,"log") | strcmp(opt,"bi") ) )
  68.       error(["d2c: illegal opt passed=",opt]);
  69.     endif
  70.   elseif(!is_sample(opt))
  71.     error("tol must be a postive scalar")
  72.   elseif(opt > 1e-2)
  73.     warning(["d2c: ridiculous error tolerance passed=",num2str(opt); ...
  74.     ", intended c2d call?"])
  75.   else
  76.     tol = opt;
  77.     opt = "log";
  78.   endif
  79.   T = sysgettsam(sys);
  80.  
  81.   if(strcmp(opt,"bi"))
  82.     # bilinear transform
  83.     # convert with bilinear transform
  84.     if (! is_digital(sys) )
  85.        error("d2c requires a discrete time system for input")
  86.     endif
  87.     [a,b,c,d,tsam,n,nz,stname,inname,outname,yd] = sys2ss(sys);
  88.  
  89.     poles = eig(a);
  90.     if( find(abs(poles-1) < 200*(n+nz)*eps) )
  91.       warning("d2c: some poles very close to one.  May get bad results.");
  92.     endif
  93.  
  94.     I = eye(size(a));
  95.     tk = 2/sqrt(T);
  96.     A = (2/T)*(a-I)/(a+I);
  97.     iab = (I+a)\b;
  98.     B = tk*iab;
  99.     C = tk*(c/(I+a));
  100.     D = d- (c*iab);
  101.     stnamec = strappend(stname,"_c");
  102.     csys = ss2sys(A,B,C,D,0,rows(A),0,stnamec,inname,outname);
  103.   elseif(strcmp(opt,"log"))
  104.     sys = sysupdate(sys,"ss");
  105.     [n,nz,m,p] = sysdimensions(sys);
  106.   
  107.     if(nz == 0)
  108.       warning("d2c: all states continuous; setting outputs to agree");
  109.       csys = syssetsignals(sys,"yd",zeros(1,1:p));
  110.       return;
  111.     elseif(n != 0)
  112.       warning(["d2c: n=",num2str(n),">0; performing c2d first"]);
  113.       sys = c2d(sys,T);
  114.     endif
  115.     [a,b] = sys2ss(sys);
  116.   
  117.     [ma,na] = size(a);
  118.     [mb,nb] = size(b);
  119.   
  120.     if(isempty(b) )
  121.       warning("d2c: empty b matrix");
  122.       Amat = a;
  123.     else
  124.       Amat = [a, b; zeros(nb,na), eye(nb)];
  125.     endif
  126.   
  127.     poles = eig(a);
  128.     if( find(abs(poles) < 200*(n+nz)*eps) )
  129.       warning("d2c: some poles very close to zero.  logm not performed");
  130.       Mtop = zeros(ma, na+nb);
  131.     elseif( find(abs(poles-1) < 200*(n+nz)*eps) )
  132.       warning("d2c: some poles very close to one.  May get bad results.");
  133.       logmat = real(logm(Amat)/T);
  134.       Mtop = logmat(1:na,:);
  135.     else
  136.       logmat = real(logm(Amat)/T);
  137.       Mtop = logmat(1:na,:);
  138.     endif
  139.   
  140.     # perform simplistic, stupid optimization approach.
  141.     # should re-write with a Davidson-Fletcher CG approach
  142.     mxthresh = norm(Mtop);
  143.     if(mxthresh == 0)
  144.       mxthresh = 1;
  145.     endif
  146.     eps1 = mxthresh;    #gradient descent step size
  147.     cnt = max(20,(n*nz)*4);    #max number of iterations
  148.     newgrad=1;    #signal for new gradient
  149.     while( (eps1/mxthresh > tol) & cnt)
  150.       cnt = cnt-1;
  151.       # calculate the gradient of error with respect to Amat...
  152.       geps = norm(Mtop)*1e-8;
  153.       if(geps == 0)
  154.         geps = 1e-8;
  155.       endif
  156.       DMtop = Mtop;
  157.       if(isempty(b))
  158.         Mall = Mtop;
  159.         DMall = DMtop;
  160.       else
  161.         Mall = [Mtop; zeros(nb,na+nb)];
  162.         DMall = [DMtop; zeros(nb,na+nb) ];
  163.       endif
  164.   
  165.       if(newgrad)
  166.         GrMall = zeros(size(Mall));
  167.         for ii=1:rows(Mtop)
  168.           for jj=1:columns(Mtop)
  169.         DMall(ii,jj) = Mall(ii,jj) + geps;
  170.             GrMall(ii,jj) = norm(Amat - expm(DMall*T),'fro') ...
  171.           - norm(Amat-expm(Mall*T),'fro');
  172.             DMall(ii,jj) = Mall(ii,jj);
  173.           endfor
  174.         endfor
  175.         GrMall = GrMall/norm(GrMall,1);
  176.         newgrad = 0;
  177.       endif
  178.   
  179.       #got a gradient, now try to use it
  180.       DMall = Mall-eps1*GrMall;
  181.   
  182.       FMall = expm(Mall*T);
  183.       FDMall = expm(DMall*T);
  184.       FmallErr = norm(Amat - FMall);
  185.       FdmallErr = norm(Amat - FDMall);
  186.       if( FdmallErr < FmallErr)
  187.         Mtop = DMall(1:na,:);
  188.         eps1 = min(eps1*2,1e12);
  189.         newgrad = 1;
  190.       else
  191.         eps1 = eps1/2;
  192.       endif
  193.   
  194.       if(FmallErr == 0)
  195.         eps1 = 0;
  196.       endif
  197.       
  198.     endwhile
  199.   
  200.     [aa,bb,cc,dd,tsam,nn,nz,stnam,innam,outnam,yd] = sys2ss(sys);
  201.     aa = Mall(1:na,1:na);
  202.     if(!isempty(b))
  203.       bb = Mall(1:na,(na+1):(na+nb));
  204.     endif
  205.     csys = ss2sys(aa,bb,cc,dd,0,na,0,stnam,innam,outnam);
  206.     
  207.     # update names
  208.     nn = sysdimensions(sys);
  209.     for ii = (nn+1):na
  210.       strval = sprintf("%s_c",sysgetsignals(csys,"st",ii,1));
  211.       csys = syssetsignals(csys,"st",strval,ii);
  212.     endfor
  213.   endif
  214.  
  215.   implicit_str_to_num_ok = save_val;    # restore value
  216. endfunction
  217.