Mercurial > hg > ltpda
view m-toolbox/classes/+utils/@math/pfallpz.m @ 19:69e3d49b4b0c database-connection-manager
Update ltpda_uo.fromRepository
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Mon, 05 Dec 2011 16:20:06 +0100 |
parents | f0afece42f48 |
children |
line wrap: on
line source
% PFALLPZ all pass filtering to stabilize TF poles and zeros. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % DESCRIPTION: % % All pass filtering in order to stabilize transfer function poles and % zeros. It inputs a partial fraction expanded discrete model and % outputs a pole-zero minimum phase system % % CALL: % % [resp,np] = pfallpz(ir,ip,id,mresp,f,fs) % [resp,np] = pfallpz(ir,ip,id,mresp,f,fs,minphase) % [resp,np,nz] = pfallpz(ir,ip,id,mresp,f,fs,minphase) % % INPUTS: % % ir: are residues % ip: are poles % id: is direct term % f: is the frequancies vector in (Hz) % fs: is the sampling frequency in (Hz) % minphase: is a flag assuming true (output a minimum phase system) or % false (output a stable non minimum phase system) values. Default, % false % % OUTPUTS: % % resp: is the functions phase frequency response % np: are the new stable poles % % NOTE: % % This function make use of signal analysis toolbox functions % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % VERSION: $Id: pfallpz.m,v 1.6 2009/06/10 15:47:00 luigi Exp $ % % HISTORY: 12-09-2008 L Ferraioli % Creation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function varargout = pfallpz(ir,ip,id,mresp,f,fs,varargin) % Reshaping [a,b] = size(ir); if a<b ir = ir.'; % reshape as a column vector end [a,b] = size(ip); if a<b ip = ip.'; % reshape as a column vector end [a,b] = size(f); if a<b f = f.'; % reshape as a column vector end [a,b] = size(id); if a > b id = id.'; % reshape as a row id = id(1,:); % taking the first row (the function can handle only simple constant direct terms) end if isempty(fs) fs = 1; end [a,b] = size(fs); if a ~= b disp(' Fs has to be a number. Only first term will be considered! ') fs = fs(1); end if nargin == 7 minphase = varargin{1}; else minphase = false; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% [Na,Nb] = size(ir); np = zeros(Na,Nb); nz = zeros(Na,Nb); for nn = 1:Nb r = ir(:,nn); d = id(1,nn); p = ip; % iresp = mresp(:,nn); % k = sum(r)+d; % stabilizing poles sp = p; unst = abs(p) > 1; sp(unst) = 1./conj(sp(unst)); s = cos((2*pi/fs).*f) + 1i.*sin((2*pi/fs).*f); pp = p(unst); psp = sp(unst); for ii = 1:length(s) nterm = 1; for jj = 1:length(sp(unst)) nterm = nterm.*(s(ii)-pp(jj))./(s(ii)-psp(jj)); end phs(ii,1) = angle(nterm); end resp(:,nn) = mresp(:,nn).*(cos(phs)+1i.*sin(phs)); % output stable poles np(:,nn) = sp; if minphase if d~=0 error('!!!Minimum phase filers can be obtained only when direct term is zero') end % finding zeros % N = Na+1; % [mults, idx] = mpoles(p,1e-15,0); % checking for poles multiplicity % p = p(idx); % re-arrange poles & residues % r = r(idx); % den = poly(p); % num = conv(den,d); % for i=1:Na % temp = poly( p([1:(i-mults(i)), (i+1):Na]) ); % num = num + [r(i)*temp zeros(1,N-length(temp))]; % end % zrs = roots(num); D = 0; % direct term of sigma A = diag(p); B = ones(Na,1); C = zeros(1,Na); % Real poles have real residues, complex poles have comples residues cindex=zeros(1,Na); for m=1:Na if imag(p(m))~=0 if m==1 cindex(m)=1; else if cindex(m-1)==0 || cindex(m-1)==2 cindex(m)=1; cindex(m+1)=2; else cindex(m)=2; end end end end for kk = 1:Na if cindex(kk) == 1 A(kk,kk)=real(p(kk)); A(kk,kk+1)=imag(p(kk)); A(kk+1,kk)=-1*imag(p(kk)); A(kk+1,kk+1)=real(p(kk)); B(kk,1) = 2; B(kk+1,1) = 0; C(1,kk) = real(r(kk,1)); C(1,kk+1) = imag(r(kk,1)); elseif cindex(kk) == 0 % real pole C(1,kk) = r(kk,1); end end [zrs,p2,k] = ss2zp(A,B,C,D,1); % stabilizing zeros szrs = zrs; % willing to work with columns [a,b] = size(szrs); if a<b szrs = szrs.'; % reshape as a column vector zrs = zrs.'; end % adding the zero at the origin zrs = [0;zrs]; szrs = [0;szrs]; % do stabilization zunst = abs(zrs) > 1; szrs(zunst) = 1./conj(zrs(zunst)); zzrs = zrs(zunst); zszrs = szrs(zunst); for ii = 1:length(s) nterm = 1; for jj = 1:length(szrs(zunst)) nterm = nterm.*(s(ii)-zszrs(jj))./(s(ii)-zzrs(jj)); end zphs(ii,1) = angle(nterm); end resp(:,nn) = resp(:,nn).*(cos(zphs)+1i.*sin(zphs)); % output stable zeros nz(:,nn) = szrs; end end % output if nargout == 1 varargout{1} = resp; elseif nargout == 2 varargout{1} = resp; varargout{2} = np; elseif (nargout == 3) && minphase varargout{1} = resp; varargout{2} = np; varargout{3} = nz; else error('Too many output arguments!') end end