Mercurial > hg > ltpda
comparison m-toolbox/classes/@ssm/bode.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f0afece42f48 |
---|---|
1 % BODE makes a bode plot from the given inputs to outputs. | |
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
3 % | |
4 % DESCRIPTION: BODE makes a bode plot from the given inputs to outputs. | |
5 % | |
6 % CALL: mat_out = bode(sys, pl) | |
7 % mat_out = bode(sys, 'key1', 'option1') | |
8 % | |
9 % INPUTS: | |
10 % 'sys' - ssm object | |
11 % 'pl' - plist of options | |
12 % | |
13 % OUTPUTS: | |
14 % | |
15 % 'mat_out' - matrix of output AOs containing the requested responses. | |
16 % | |
17 % <a href="matlab:utils.helper.displayMethodInfo('ssm', 'bode')">Parameter Sets</a> | |
18 % | |
19 % VERSION: $Id: bode.m,v 1.40 2011/04/17 21:28:05 adrien Exp $ | |
20 % | |
21 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
22 | |
23 function varargout = bode(varargin) | |
24 | |
25 % use the caller is method flag | |
26 callerIsMethod = utils.helper.callerIsMethod; | |
27 | |
28 % Check if this is a call for parameters | |
29 if utils.helper.isinfocall(varargin{:}) | |
30 varargout{1} = getInfo(varargin{3}); | |
31 return | |
32 end | |
33 | |
34 if callerIsMethod | |
35 % assume bode(sys,pl) | |
36 system = varargin{1}; | |
37 pl = applyDefaults(getDefaultPlist(), varargin{2}); | |
38 else | |
39 % starting initial checks | |
40 | |
41 utils.helper.msg(utils.const.msg.PROC3, ['running ', mfilename]); | |
42 | |
43 % Collect input variable names | |
44 in_names = cell(size(varargin)); | |
45 for ii = 1:nargin,in_names{ii} = inputname(ii);end | |
46 | |
47 % Collect all AOs and plists | |
48 [system, ssm_invars, rest] = utils.helper.collect_objects(varargin(:), 'ssm', in_names); | |
49 [pl, invars2, rest] = utils.helper.collect_objects(rest(:), 'plist'); | |
50 | |
51 % combine default plist | |
52 if ~isempty(rest) | |
53 pl = combine(pl, plist(rest{:})); | |
54 end | |
55 pl = combine(pl, getDefaultPlist()); | |
56 | |
57 % retrieving system's infos | |
58 if numel(system)~=1 | |
59 error('we should have only one ssm and one plist object as an input') | |
60 end | |
61 | |
62 inhist = system.hist; | |
63 if ~system.isStable | |
64 error('input ssm is not stable!') | |
65 end | |
66 | |
67 end | |
68 | |
69 if (system.isnumerical == 0) | |
70 warning(['The system ' system.name ' is symbolic. The system is made numeric for bode calculation.']) | |
71 sys = copy(system,1); | |
72 sys.keepParameters; | |
73 else | |
74 sys = system; | |
75 end | |
76 | |
77 % Compute frequency vector | |
78 f = pl.find('f'); | |
79 if isempty(f) | |
80 % finding "f2" | |
81 if isempty(pl.find('f2')) | |
82 if sys.timestep>0 | |
83 f2 = 0.5/sys.timestep; | |
84 else | |
85 f2 = 1; | |
86 end | |
87 else | |
88 f2 = pl.find('f2'); | |
89 end | |
90 % finding "f1" | |
91 if isempty(pl.find('f1')) | |
92 f1 = f2*1e-5; | |
93 else | |
94 f1 = pl.find('f1'); | |
95 end | |
96 nf = pl.find('nf'); | |
97 scale = pl.find('scale'); | |
98 % building "f" vector | |
99 switch lower(scale) | |
100 case 'log' | |
101 f = logspace(log10(f1), log10(f2), nf); | |
102 case 'lin' | |
103 f = linspace(f1, f2, nf); | |
104 otherwise | |
105 error('### Unknown scale option'); | |
106 end | |
107 end | |
108 | |
109 % Is the f vector in an AO? | |
110 if isa(f, 'ao') && (isa(f.data, 'fsdata') || isa(f.data, 'xydata')) | |
111 f = f.x; | |
112 end | |
113 | |
114 % Compute omega | |
115 w = 2*pi*f; | |
116 | |
117 if find(pl, 'reorganize') | |
118 sys = reorganize(sys, pl, 'set', 'for bode', 'internal', 'internal'); | |
119 end | |
120 | |
121 % getting system's i/o sizes | |
122 timestep = sys.timestep; | |
123 fs = 1/timestep; | |
124 | |
125 inputSizes = sys.inputsizes; | |
126 outputSizes = sys.outputsizes; | |
127 | |
128 Nin = inputSizes(1); | |
129 NstatesOut = outputSizes(1); | |
130 NoutputsOut = outputSizes(2); | |
131 | |
132 A = sys.amats{1,1}; | |
133 Coutputs = sys.cmats{2,1}; | |
134 Cstates = sys.cmats{1,1}; | |
135 B = sys.bmats{1,1}; | |
136 D = sys.dmats{2,1}; | |
137 Dstates = zeros(size(Cstates,1), size(D,2)); | |
138 | |
139 % bode computation | |
140 resps = ssm.doBode(A, B, [Cstates; Coutputs], [Dstates; D], w, timestep); | |
141 | |
142 numericOutput = pl.find('numeric output'); | |
143 | |
144 % build AO | |
145 if numericOutput | |
146 % just output pure numbers | |
147 count = 1; | |
148 | |
149 for ii=1:Nin | |
150 for oo=1:NoutputsOut | |
151 y = squeeze(resps(NstatesOut+oo,ii,:)); | |
152 varargout{count} = y; | |
153 count = count + 1; | |
154 end | |
155 end | |
156 return; | |
157 else | |
158 % First make outputs and set the data | |
159 ao_out = ao.initObjectWithSize(NstatesOut+NoutputsOut, Nin); | |
160 for ii=1:Nin | |
161 for oo=1:NstatesOut | |
162 ao_out(oo,ii).setData(fsdata(f, squeeze(resps(oo,ii,:)), fs)); | |
163 end | |
164 for oo=1:NoutputsOut | |
165 y = squeeze(resps(NstatesOut+oo,ii,:)); | |
166 fsd = fsdata(f, y, fs); | |
167 ao_out(NstatesOut+oo,ii).setData(fsd); | |
168 end | |
169 end | |
170 | |
171 if ~callerIsMethod | |
172 % set names, units, description, and add history | |
173 isysStr = sys.name; | |
174 | |
175 for ii=1:Nin | |
176 for oo=1:NstatesOut | |
177 ao_out(oo,ii).setName( [sys.inputs(1).ports(ii).name '-->' sys.outputs(1).ports(oo).name]); | |
178 ao_out(oo,ii).setXunits('Hz'); | |
179 ao_out(oo,ii).setYunits( simplify(sys.outputs(1).ports(oo).units / sys.inputs(1).ports(ii).units)); | |
180 ao_out(oo,ii).setDescription(... | |
181 ['Bode of ' isysStr, ' from ', sys.inputs(1).ports(ii).description,... | |
182 ' to ' sys.outputs(1).ports(oo).description]); | |
183 end | |
184 for oo=1:NoutputsOut | |
185 ao_out(NstatesOut+oo,ii).setName( [sys.inputs(1).ports(ii).name '-->' sys.outputs(2).ports(oo).name]); | |
186 ao_out(NstatesOut+oo,ii).setXunits('Hz'); | |
187 ao_out(NstatesOut+oo,ii).setYunits( simplify(sys.outputs(2).ports(oo).units / sys.inputs(1).ports(ii).units)); | |
188 ao_out(NstatesOut+oo,ii).setDescription(... | |
189 ['Bode of ' isysStr, ' from ', sys.inputs(1).ports(ii).description,... | |
190 ' to ' sys.outputs(2).ports(oo).description]); | |
191 end | |
192 end | |
193 end | |
194 end | |
195 | |
196 %% construct output matrix object | |
197 out = matrix(ao_out); | |
198 if callerIsMethod | |
199 % do nothing | |
200 else | |
201 myinfo = getInfo('None'); | |
202 out.addHistory(myinfo, pl , ssm_invars(1), inhist ); | |
203 end | |
204 | |
205 %% Set output depending on nargout | |
206 if nargout == 1; | |
207 varargout = {out}; | |
208 elseif nargout == 0; | |
209 iplot(ao_out); | |
210 else | |
211 error('Wrong number of outputs') | |
212 end | |
213 | |
214 end | |
215 | |
216 | |
217 %-------------------------------------------------------------------------- | |
218 % Get Info Object | |
219 %-------------------------------------------------------------------------- | |
220 function ii = getInfo(varargin) | |
221 | |
222 if nargin == 1 && strcmpi(varargin{1}, 'None') | |
223 sets = {}; | |
224 pl = []; | |
225 else | |
226 sets = {'Default'}; | |
227 pl = getDefaultPlist; | |
228 end | |
229 % Build info object | |
230 ii = minfo(mfilename, 'ssm', 'ltpda', utils.const.categories.sigproc, '$Id: bode.m,v 1.40 2011/04/17 21:28:05 adrien Exp $', sets, pl); | |
231 end | |
232 | |
233 %-------------------------------------------------------------------------- | |
234 % Get Default Plist | |
235 %-------------------------------------------------------------------------- | |
236 function pl = getDefaultPlist() | |
237 pl = ssm.getInfo('reorganize', 'for bode').plists; | |
238 pl.remove('set'); | |
239 | |
240 p = param({'f', 'A frequency vector (replaces f1, f2 and nf).'}, paramValue.EMPTY_DOUBLE) ; | |
241 pl.append(p); | |
242 | |
243 p = param({'f2', 'The maximum frequency. Default is Nyquist or 1Hz.'}, paramValue.EMPTY_DOUBLE); | |
244 pl.append(p); | |
245 | |
246 p = param({'f1', 'The minimum frequency. Default is f2*1e-5.'}, paramValue.EMPTY_DOUBLE); | |
247 pl.append(p); | |
248 | |
249 p = param({'nf', 'The number of frequency bins.'}, paramValue.DOUBLE_VALUE(1000)); | |
250 pl.append(p); | |
251 | |
252 p = param({'scale', 'Distribute frequencies on a ''log'' or ''lin'' scale.'}, {1, {'log', 'lin'}, paramValue.SINGLE}); | |
253 pl.append(p); | |
254 | |
255 p = param({'reorganize', 'When set to 0, this means the ssm does not need be modified to match the requested i/o. Faster but dangerous!'}, paramValue.TRUE_FALSE); | |
256 pl.append(p); | |
257 | |
258 p = param({'numeric output', 'When set to ture, the output of bode will be purely numeric - no analysis objects.'}, paramValue.FALSE_TRUE); | |
259 pl.append(p); | |
260 | |
261 end | |
262 | |
263 | |
264 |