1 ## Copyright (C) 2009, 2010, 2011, 2012 Lukas F. Reichlin
3 ## This file is part of LTI Syncope.
5 ## LTI Syncope is free software: you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation, either version 3 of the License, or
8 ## (at your option) any later version.
10 ## LTI Syncope is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ## GNU General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with LTI Syncope. If not, see <http://www.gnu.org/licenses/>.
19 ## @deftypefn {Function File} {@var{s} =} tf (@var{"s"})
20 ## @deftypefnx {Function File} {@var{z} =} tf (@var{"z"}, @var{tsam})
21 ## @deftypefnx {Function File} {@var{sys} =} tf (@var{sys})
22 ## @deftypefnx {Function File} {@var{sys} =} tf (@var{num}, @var{den}, @dots{})
23 ## @deftypefnx {Function File} {@var{sys} =} tf (@var{num}, @var{den}, @var{tsam}, @dots{})
24 ## Create or convert to transfer function model.
29 ## LTI model to be converted to transfer function.
31 ## Numerator or cell of numerators. Each numerator must be a row vector
32 ## containing the coefficients of the polynomial in descending powers of
33 ## the transfer function variable.
34 ## num@{i,j@} contains the numerator polynomial from input j to output i.
35 ## In the SISO case, a single vector is accepted as well.
37 ## Denominator or cell of denominators. Each denominator must be a row vector
38 ## containing the coefficients of the polynomial in descending powers of
39 ## the transfer function variable.
40 ## den@{i,j@} contains the denominator polynomial from input j to output i.
41 ## In the SISO case, a single vector is accepted as well.
43 ## Sampling time in seconds. If @var{tsam} is not specified, a continuous-time
46 ## Optional pairs of properties and values.
47 ## Type @command{set (tf)} for more information.
53 ## Transfer function model.
59 ## octave:1> s = tf ("s");
60 ## octave:2> G = 1/(s+1)
62 ## Transfer function "G" from input "u1" to output ...
68 ## Continuous-time model.
73 ## octave:3> z = tf ("z", 0.2);
74 ## octave:4> H = 0.095/(z-0.9)
76 ## Transfer function "H" from input "u1" to output ...
82 ## Sampling time: 0.2 s
83 ## Discrete-time model.
88 ## octave:5> num = @{[1, 5, 7], [1]; [1, 7], [1, 5, 5]@};
89 ## octave:6> den = @{[1, 5, 6], [1, 2]; [1, 8, 6], [1, 3, 2]@};
90 ## octave:7> sys = tf (num, den)
92 ## Transfer function "sys" from input "u1" to output ...
102 ## Transfer function "sys" from input "u2" to output ...
112 ## Continuous-time model.
120 ## Author: Lukas Reichlin <lukas.reichlin@gmail.com>
121 ## Created: September 2009
124 function sys = tf (num = {}, den = {}, varargin)
126 ## model precedence: frd > ss > zpk > tf > double
127 ## inferiorto ("frd", "ss", "zpk"); # error if de-commented. bug in octave?
128 superiorto ("double");
130 argc = 0; # initialize argument count
134 tsam = -2; # undefined sampling time
135 tfvar = "x"; # undefined transfer function variable
138 if (isa (num, "tf")) # already in tf form sys = tf (tfsys)
141 elseif (isa (num, "lti")) # another lti object sys = tf (sys)
142 [sys, numlti] = __sys2tf__ (num);
143 sys.lti = numlti; # preserve lti properties
145 elseif (is_real_matrix (num)) # static gain sys = tf (4), sys = tf (matrix)
146 num = num2cell (num);
147 num = __vec2tfpoly__ (num);
149 den = tfpolyones (p, m); # denominators are all 1
150 tsam = -2; # undefined sampling time
151 tfvar = "x"; # undefined transfer function variable
152 elseif (ischar (num)) # s = tf ("s")
154 num = __vec2tfpoly__ ([1, 0]);
155 den = __vec2tfpoly__ ([1]);
162 if (ischar (num) && issample (den, -1)) # z = tf ("z", 0.3)
165 num = __vec2tfpoly__ ([1, 0]);
166 den = __vec2tfpoly__ ([1]);
167 else # sys = tf (num, den)
168 num = __vec2tfpoly__ (num);
169 den = __vec2tfpoly__ (den);
174 otherwise # default case sys = tf (num, den, ...)
175 num = __vec2tfpoly__ (num);
176 den = __vec2tfpoly__ (den);
177 argc = numel (varargin); # number of additional arguments after num and den
178 if (issample (varargin{1}, -10)) # sys = tf (num, den, tsam, "prop1", val1, ...)
179 tsam = varargin{1}; # sampling time, could be 0 as well
180 argc--; # tsam is not a property-value pair
186 if (argc > 0) # if there are any properties and values ...
187 varargin = varargin(2:end); # remove tsam from property-value list
189 else # sys = tf (num, den, "prop1", val1, ...)
190 tsam = 0; # continuous-time
195 [p, m] = __tf_dim__ (num, den); # determine number of outputs and inputs
197 tfdata = struct ("num", {num},
200 "inv", false); # struct for tf-specific data
202 ltisys = lti (p, m, tsam); # parent class for general lti data
204 sys = class (tfdata, "tf", ltisys); # create tf object
206 if (argc > 0) # if there are any properties and values, ...
207 sys = set (sys, varargin{:}); # use the general set function