summaryrefslogtreecommitdiff
path: root/modules/cacsd/macros/bode.sci
diff options
context:
space:
mode:
Diffstat (limited to 'modules/cacsd/macros/bode.sci')
-rwxr-xr-xmodules/cacsd/macros/bode.sci207
1 files changed, 207 insertions, 0 deletions
diff --git a/modules/cacsd/macros/bode.sci b/modules/cacsd/macros/bode.sci
new file mode 100755
index 000000000..d1cba667e
--- /dev/null
+++ b/modules/cacsd/macros/bode.sci
@@ -0,0 +1,207 @@
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 1985-2010 - INRIA - Serge Steer
+// This file must be used under the terms of the CeCILL.
+// This source file is licensed as described in the file COPYING, which
+// you should have received as part of this distribution. The terms
+// are also available at
+// http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+
+function [] = bode(varargin)
+ rhs = size(varargin)
+
+ if rhs == 0 then
+ s = poly(0, "s");
+ h1 = syslin("c", (s^2+2*0.9*10*s+100)/(s^2+2*0.3*10.1*s+102.01));
+ num = 22801+4406.18*s+382.37*s^2+21.02*s^3+s^4;
+ den = 22952.25+4117.77*s+490.63*s^2+33.06*s^3+s^4;
+ h2 = syslin("c", num/den);
+
+ bode([h1; h2], 0.01, 100, ["h1"; "h2"]);
+ return;
+ end
+
+ rad = %f;
+ if type(varargin($)) == 10 then
+ if varargin($) == "rad" then
+ rad = %t;
+ rhs = rhs-1;
+ if type(varargin($-1)) == 10 then
+ comments = varargin($-1);
+ rhs = rhs-1;
+ else
+ comments = [];
+ end
+ else
+ comments = varargin($);
+ rhs = rhs-1;
+ end
+ else
+ comments = [];
+ end
+ fname = "bode"; // For error messages
+ fmax = [];
+ discr = %f; // For Shannon limit
+ if or(typeof(varargin(1)) == ["state-space" "rational"]) then
+// sys, fmin, fmax [,pas] or sys, frq
+ refdim = 1; // for error message
+ discr = varargin(1).dt<>"c";
+ if rhs == 1 then // sys
+ [frq, repf] = repfreq(varargin(1), 1d-3, 1d3);
+ elseif rhs == 2 then // sys, frq
+ if size(varargin(2), 2) < 2 then
+ error(msprintf(_("%s: Wrong size for input argument #%d: A row vector with length>%d expected.\n"), ..
+ fname, 2, 1))
+ end
+ [frq, repf] = repfreq(varargin(1:rhs));
+ elseif or(rhs == (3:4)) then // sys, fmin, fmax [,pas]
+ [frq, repf] = repfreq(varargin(1:rhs));
+ else
+ error(msprintf(_("%s: Wrong number of input arguments: %d to %d expected.\n"), fname, 1, 5))
+ end
+ [phi, d] = phasemag(repf);
+ if rhs >= 3 then fmax = varargin(3); end
+ elseif type(varargin(1)) == 1 then
+// frq, db, phi [,comments] or frq, repf [,comments]
+ refdim = 2;
+ select rhs
+ case 2 then // frq,repf
+ frq = varargin(1);
+ if size(frq, 2) < 2 then
+ error(msprintf(_("%s: Wrong size for input argument #%d: A row vector with length>%d expected.\n"), ..
+ fname, 1, 1))
+ end
+ if size(frq, 2) <> size(varargin(2), 2) then
+ error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same column dimensions expected.\n"), ..
+ fname, 1, 2))
+ end
+ [phi, d] = phasemag(varargin(2));
+ case 3 then // frq, db, phi
+ [frq, d, phi] = varargin(1:rhs);
+ if size(frq, 2) <> size(d, 2) then
+ error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same column dimensions expected.\n"), ..
+ fname, 1, 2))
+ end
+ if size(frq, 2) <> size(phi, 2) then
+ error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same column dimensions expected.\n"), ..
+ fname, 1, 3))
+ end
+ else
+ error(msprintf(_("%s: Wrong number of input arguments: %d to %d expected.\n"), fname, 2, 4))
+ end
+ else
+ error(msprintf(_("%s: Wrong type for input argument #%d: Linear dynamical system or row vector of floats expected.\n"),fname,1))
+ end
+ frq = frq';
+ d = d';
+ phi = phi';
+ [n, mn] = size(d);
+
+ if comments == [] then
+ hx = 0.48;
+ else
+ if size(comments, "*") <> mn then
+ error(mprintf(_("%s: Incompatible input arguments #%d and #%d: Same number of elements expected.\n"), ...
+ fname, refdim, rhs+1))
+ end
+ hx = 0.43;
+ end
+
+ fig = gcf();
+ immediate_drawing = fig.immediate_drawing;
+ fig.immediate_drawing = "off";
+
+ sciCurAxes = gca();
+ axes = sciCurAxes;
+ wrect = axes.axes_bounds;
+
+
+// Magnitude
+ axes.axes_bounds = [wrect(1)+0, wrect(2)+0, wrect(3)*1.0, wrect(4)*hx*0.95];
+ axes.data_bounds = [min(frq), min(d); max(frq), max(d)];
+ axes.log_flags = "lnn";
+ axes.grid = color("lightgrey")*ones(1, 3);
+ axes.axes_visible = "on";
+ axes.clip_state = "clipgrf";
+ if size(d, 2) > 1 & size(frq, 2) == 1 then
+ xpolys(frq(:, ones(1, mn)), d, 1:mn);
+ else
+ xpolys(frq, d, 1:mn);
+ end
+// Set datatips info
+ e = gce();
+
+ for i=1:size(e.children, "*")
+ e.children(i).display_function = "formatBodeMagTip"
+ end
+
+ if discr & fmax <> [] & max(frq) < fmax then
+ xpoly(max(frq)*[1; 1], axes.y_ticks.locations([1 $]));
+ e = gce();
+ e.foreground = 5;
+ end
+ xtitle("", _("Frequency (Hz)"), _("Magnitude (dB)"));
+
+// Phase
+ axes = newaxes();
+ axes.axes_bounds = [wrect(1)+0, wrect(2)+wrect(4)*hx, wrect(3)*1.0, wrect(4)*hx*0.95];
+ axes.data_bounds = [min(frq), min(phi); max(frq), max(phi)];
+ axes.log_flags = "lnn";
+ axes.grid = color("lightgrey")*ones(1, 3);
+ axes.axes_visible = "on";
+ axes.clip_state = "clipgrf";
+ if size(phi, 2) > 1 & size(frq, 2) == 1 then
+ xpolys(frq(:, ones(1, mn)), phi, 1:mn);
+ else
+ xpolys(frq, phi, 1:mn);
+ end
+ ephi = gce();
+// Set datatips info
+ for i=1:size(ephi.children, "*")
+ ephi.children(i).display_function = "formatBodePhaseTip";
+ end
+
+ if discr & fmax <> [] & max(frq) < fmax then
+ xpoly(max(frq)*[1; 1], axes.y_ticks.locations([1 $]));
+ e = gce();
+ e.foreground = 5;
+ end
+ xtitle("", _("Frequency (Hz)"), _("Phase (degree)"));
+// Create legend
+ if comments <> [] then
+ c = captions(ephi.children, comments, "lower_caption");
+ c.background = get(gcf(), "background");
+ end
+ fig.immediate_drawing = immediate_drawing;
+// Return to the previous scale
+ set("current_axes", sciCurAxes);
+
+ if rad == %t then
+// This function modifies the Bode diagrams for a rad/s display instead of Hz.
+// h is a hanlde of a figure containing Bode diagrams.
+// Ref: http://forge.scilab.org/index.php/p/cpge/source/tree/HEAD/macros/bode_Hz2rad_2.sci
+ labels = [_("Phase (degree)"); _("Magnitude (dB)")];
+ pos_h = [9, 5];
+ for k=1:2
+ for i=1:size(fig.children(k).children, 1)
+ if fig.children(k).children(i).type == "Compound"
+ for j=1:size(fig.children(k).children(i).children, 1)
+ fig.children(k).children(i).children(j).data(:, 1) = fig.children(k).children(i).children(j).data(:, 1)*2*%pi;
+ end
+
+ // h.children(k).title.text = h.children(k).y_label.text;
+ xmin1 = fig.children(k).data_bounds(1)*2*%pi;
+ xmax1 = fig.children(k).data_bounds(2)*2*%pi;
+ ymin1 = fig.children(k).data_bounds(3);
+ ymax1 = fig.children(k).data_bounds(4);
+
+ rect = [xmin1, ymin1, xmax1, ymax1];
+ nb_dec = log(xmax1/xmin1)/log(10);
+ fig.children(k).x_label.text = _("Frequency (rad/s)");
+ fig.children(k).x_location = "bottom";
+ fig.children(k).y_label.text = labels(k);
+ replot(rect, fig.children(k));
+ end
+ end
+ end
+ end
+endfunction