From: <par...@us...> - 2010-10-27 20:37:13
|
Revision: 7884 http://octave.svn.sourceforge.net/octave/?rev=7884&view=rev Author: paramaniac Date: 2010-10-27 20:37:07 +0000 (Wed, 27 Oct 2010) Log Message: ----------- control: include zeros and poles in frequency vector when plotting (thanks to JP Keller) Modified Paths: -------------- trunk/octave-forge/main/control/inst/@ss/__sys2frd__.m trunk/octave-forge/main/control/inst/@tf/__sys2frd__.m trunk/octave-forge/main/control/inst/__frequency_response__.m Added Paths: ----------- trunk/octave-forge/main/control/inst/__frequency_vector__.m Removed Paths: ------------- trunk/octave-forge/main/control/inst/__frequency_range__.m Modified: trunk/octave-forge/main/control/inst/@ss/__sys2frd__.m =================================================================== --- trunk/octave-forge/main/control/inst/@ss/__sys2frd__.m 2010-10-27 09:34:34 UTC (rev 7883) +++ trunk/octave-forge/main/control/inst/@ss/__sys2frd__.m 2010-10-27 20:37:07 UTC (rev 7884) @@ -25,8 +25,7 @@ function [retsys, retlti] = __sys2frd__ (sys, w = []) if (isempty (w)) # case sys = frd (sys) - [dec_min, dec_max] = __frequency_range__ (sys); - w = logspace (dec_min, dec_max, 500); + w = __frequency_vector__ (sys); endif H = __freqresp__ (sys, w); Modified: trunk/octave-forge/main/control/inst/@tf/__sys2frd__.m =================================================================== --- trunk/octave-forge/main/control/inst/@tf/__sys2frd__.m 2010-10-27 09:34:34 UTC (rev 7883) +++ trunk/octave-forge/main/control/inst/@tf/__sys2frd__.m 2010-10-27 20:37:07 UTC (rev 7884) @@ -25,8 +25,7 @@ function [retsys, retlti] = __sys2frd__ (sys, w = []) if (isempty (w)) # case sys = frd (sys) - [dec_min, dec_max] = __frequency_range__ (sys); - w = logspace (dec_min, dec_max, 500); + w = __frequency_vector__ (sys); endif H = __freqresp__ (sys, w); Deleted: trunk/octave-forge/main/control/inst/__frequency_range__.m =================================================================== --- trunk/octave-forge/main/control/inst/__frequency_range__.m 2010-10-27 09:34:34 UTC (rev 7883) +++ trunk/octave-forge/main/control/inst/__frequency_range__.m 2010-10-27 20:37:07 UTC (rev 7884) @@ -1,122 +0,0 @@ -## Copyright (C) 1996, 2000, 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{dec_min}, @var{dec_max}] =} __frequency_range__ (@var{sys}) -## Get default range of frequencies based on cutoff frequencies of system -## poles and zeros. -## Frequency range is the interval -## @iftex -## @tex -## $ [ 10^{w_{min}}, 10^{w_{max}} ] $ -## @end tex -## @end iftex -## @ifinfo -## [10^@var{wmin}, 10^@var{wmax}] -## @end ifinfo -## -## Used internally in @command{margin} (@command{bode}, @command{nyquist}) -## @end deftypefn - -## Adapted-By: Lukas Reichlin <luk...@gm...> -## Date: October 2009 -## Version: 0.1 - -function [dec_min, dec_max] = __frequency_range__ (sys, wbounds = "std") - - zer = zero (sys); - pol = pole (sys); - tsam = get (sys, "tsam"); - discrete = (tsam > 0); # static gains (tsam = -1) are continuous - - ## make sure zer, pol are row vectors - pol = reshape (pol, 1, []); - zer = reshape (zer, 1, []); - - ## check for natural frequencies away from omega = 0 - if (discrete) - ## The 2nd conditions prevents log(0) in the next log command - iiz = find (abs(zer-1) > norm(zer)*eps && abs(zer) > norm(zer)*eps); - iip = find (abs(pol-1) > norm(pol)*eps && abs(pol) > norm(pol)*eps); - - ## avoid dividing empty matrices, it would work but looks nasty - if (! isempty (iiz)) - czer = log (zer(iiz))/tsam; - else - czer = []; - endif - - if (! isempty (iip)) - cpol = log (pol(iip))/tsam; - else - cpol = []; - endif - else - ## continuous - iip = find (abs(pol) > norm(pol)*eps); - iiz = find (abs(zer) > norm(zer)*eps); - - if (! isempty (zer)) - czer = zer(iiz); - else - czer = []; - endif - if (! isempty (pol)) - cpol = pol(iip); - else - cpol = []; - endif - endif - - if (isempty (iip) && isempty (iiz)) - ## no poles/zeros away from omega = 0; pick defaults - dec_min = 0; # -1 - dec_max = 2; # 3 - else - dec_min = floor (log10 (min (abs ([cpol, czer])))); - dec_max = ceil (log10 (max (abs ([cpol, czer])))); - endif - - ## expand to show the entirety of the "interesting" portion of the plot - switch (wbounds) - case "std" # standard - if (dec_min == dec_max) - dec_min -= 2; - dec_max += 2; - else - dec_min--; - dec_max++; - endif - case "ext" # extended (for nyquist) - if (any (abs (pol) < sqrt (eps))) # look for integrators - ## dec_min -= 0.5; - dec_max += 2; - else - dec_min -= 2; - dec_max += 2; - endif - otherwise - error ("frequency_range: second argument invalid"); - endswitch - - ## run discrete frequency all the way to pi - if (discrete) - dec_max = log10 (pi/tsam); - endif - -endfunction Modified: trunk/octave-forge/main/control/inst/__frequency_response__.m =================================================================== --- trunk/octave-forge/main/control/inst/__frequency_response__.m 2010-10-27 09:34:34 UTC (rev 7883) +++ trunk/octave-forge/main/control/inst/__frequency_response__.m 2010-10-27 20:37:07 UTC (rev 7884) @@ -17,7 +17,7 @@ ## -*- texinfo -*- ## Return frequency response H and frequency vector w. -## If w is empty, it will be calculated by __frequency_range__. +## If w is empty, it will be calculated by __frequency_vector__. ## Author: Lukas Reichlin <luk...@gm...> ## Created: November 2009 @@ -40,15 +40,10 @@ else warning ("frequency_response: second argument w is ignored"); endif - else - ## find interesting frequency range w if not specified - if (isempty (w)) - ## begin plot at 10^dec_min, end plot at 10^dec_max [rad/s] - [dec_min, dec_max] = __frequency_range__ (sys, wbounds); - w = logspace (dec_min, dec_max, 500); # [rad/s] - elseif (! is_real_vector (w)) - error ("frequency_response: second argument w must be a vector of frequencies"); - endif + elseif (isempty (w)) # find interesting frequency range w if not specified + w = __frequency_vector__ (sys, wbounds); + elseif (! is_real_vector (w)) + error ("frequency_response: second argument w must be a vector of frequencies"); endif ## frequency response Copied: trunk/octave-forge/main/control/inst/__frequency_vector__.m (from rev 7883, trunk/octave-forge/main/control/inst/__frequency_range__.m) =================================================================== --- trunk/octave-forge/main/control/inst/__frequency_vector__.m (rev 0) +++ trunk/octave-forge/main/control/inst/__frequency_vector__.m 2010-10-27 20:37:07 UTC (rev 7884) @@ -0,0 +1,130 @@ +## Copyright (C) 1996, 2000, 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{w} =} __frequency_vector__ (@var{sys}) +## Get default range of frequencies based on cutoff frequencies of system +## poles and zeros. +## Frequency range is the interval +## @iftex +## @tex +## $ [ 10^{w_{min}}, 10^{w_{max}} ] $ +## @end tex +## @end iftex +## @ifinfo +## [10^@var{wmin}, 10^@var{wmax}] +## @end ifinfo +## +## Used by @command{__frequency_response__} +## @end deftypefn + +## Adapted-By: Lukas Reichlin <luk...@gm...> +## Date: October 2009 +## Version: 0.2 + +function w = __frequency_vector__ (sys, wbounds = "std") + + zer = zero (sys); + pol = pole (sys); + tsam = get (sys, "tsam"); + discrete = (tsam > 0); # static gains (tsam = -1) are continuous + + ## make sure zer, pol are row vectors + pol = reshape (pol, 1, []); + zer = reshape (zer, 1, []); + + ## check for natural frequencies away from omega = 0 + if (discrete) + ## The 2nd conditions prevents log(0) in the next log command + iiz = find (abs(zer-1) > norm(zer)*eps && abs(zer) > norm(zer)*eps); + iip = find (abs(pol-1) > norm(pol)*eps && abs(pol) > norm(pol)*eps); + + ## avoid dividing empty matrices, it would work but looks nasty + if (! isempty (iiz)) + czer = log (zer(iiz))/tsam; + else + czer = []; + endif + + if (! isempty (iip)) + cpol = log (pol(iip))/tsam; + else + cpol = []; + endif + else + ## continuous + iip = find (abs(pol) > norm(pol)*eps); + iiz = find (abs(zer) > norm(zer)*eps); + + if (! isempty (zer)) + czer = zer(iiz); + else + czer = []; + endif + if (! isempty (pol)) + cpol = pol(iip); + else + cpol = []; + endif + endif + + if (isempty (iip) && isempty (iiz)) + ## no poles/zeros away from omega = 0; pick defaults + dec_min = 0; # -1 + dec_max = 2; # 3 + else + dec_min = floor (log10 (min (abs ([cpol, czer])))); + dec_max = ceil (log10 (max (abs ([cpol, czer])))); + endif + + ## expand to show the entirety of the "interesting" portion of the plot + switch (wbounds) + case "std" # standard + if (dec_min == dec_max) + dec_min -= 2; + dec_max += 2; + else + dec_min--; + dec_max++; + endif + case "ext" # extended (for nyquist) + if (any (abs (pol) < sqrt (eps))) # look for integrators + ## dec_min -= 0.5; + dec_max += 2; + else + dec_min -= 2; + dec_max += 2; + endif + otherwise + error ("frequency_range: second argument invalid"); + endswitch + + ## run discrete frequency all the way to pi + if (discrete) + dec_max = log10 (pi/tsam); + endif + + ## create frequency vector + zp = [abs(zer), abs(pol)]; + idx = find (zp > 10^dec_min & zp < 10^dec_max); + zp = zp(idx); + + w = logspace (dec_min, dec_max, 500); + w = unique ([w, zp]); # unique also sorts frequency vector + +endfunction This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |