I would like to plot a transfer function from a Simulnik file model.mdl where I used blocks From Workspace (simin) and To Workspace (simou) to start a simulation from Matlab.
And now comes the problem. I simply can't find a way to run this Simulink model in Matlab.
Here is my code;
sim('model');
h=simout/simin;
[H,omega]=freqz(h);
%plot
I get this errors;
Error evaluating parameter 'VariableName' in 'model/From
Workspace'
Caused by:
Error using sigma (line 8)
Undefined function or variable 'simin'.
What am I doing wrong?
This is my model:
Thank you so much.
Do you actually know the transfer function? Is implemented correctly in Simulink? Then the error suggests that you haven't assigned the correct variable name to your from workspace block, you just kept the default VariableName. For the frequency response you need to define your transfer function outside Simulink with tf, then use bodeplot to plot it.
(Look at the end of these answer)
But it appears to me, that you have some inputdata and some outputdata and you'd like to estimate the transfer function and finally get the frequency response of that transfer function. There is no need for Simulink to do that. Once you found your transfer function you could implement it into Simulink using the Transfer function block, feed the simulation with the From Workspace Block and display the results with Scope. But first you need the transfer function.
Assuming you have the variables inputdata and outputdata you first need to create a transfer function dataset:
% prepare data for tftest, 100 is a random chosen sampling time
tfdata = iddata(data(:,1),data(:,2),100);
then you can use tfest to estimate the transfer function with a chosen number of poles:
N = 5; % Number of poles
sys = tfest(tfdata,N);
The frequency response you get e.g. with bodeplot:
bodeplot(sys)
The function FREQZ you intended to use is just for digital filters, not for transfer functions.
Finally you can test your model with Simulink:
where the numerator of the Transfer Fcn Block is sys.num{1} and the denominator sys.den{1} (for my example).
If the graph displayed in Scope (be aware that you should disable "Limit Data points to last 5000" in the scope Settings) is similar to your outputdata the estimation was successful.
I made a testrun for your model: (fixed step solver, no continuous states, 0.0001 steptime).
Then the following code:
tfdata = iddata(inputdata,outputdata,0.0001);
N = 5;
sys = tfest(tfdata,N);
bodeplot(sys)
returning:
sys =
From input "u1" to output "y1":
-2068 s^4 + 2.89e06 s^3 + 7.017e10 s^2 + 5.205e13 s - 8.931e15
-------------------------------------------------------
s^5 + 1.034e04 s^4 + 4.552e07 s^3 + 1.114e11 s^2 + 8.337e13 s + 8.931e15
and:
or convert it to discrete:
sysd = c2d(sys,0.0001)
sysd =
From input "u1" to output "y1":
-0.0995 z^-1 + 0.4644 z^-2 - 0.7491 z^-3 + 0.5061 z^-4 - 0.1219 z^-5
-------------------------------------------------------
1 - 4.042 z^-1 + 6.554 z^-2 - 5.332 z^-3 + 2.176 z^-4 - 0.3556 z^-5
I can't help you more, and it's a homework anyway, right? So the rest is up to you. And honestly, calculate it by hand! It will be much more exact!
Well, the error message should be self-explanatory: you haven't defined your variable simin in the base workspace. Define it (as a function of time) and then your model will run.
BTW, a much better way to obtain the transfer function from your Simulink model is use dlinmod, as other people have already pointed out, or linearize if you have Simulink Control Design. Your approach is prone to noise and not very robust. It also relies on your input having all the frequency components of interest, which is unlikely. Simulink Control Design also provides frestimate to estimate the frequency response function of your model.
Take a look at dlinmod: Extract discrete-time linear state-space model around operating point (from a Simulink model).
The following code helps me:
[A B C D]=linmod2('FileNameWithoutExtension');
tf_you_want_to_get=tf(minreal(ss(A,B,C,D)))
Related
I used the PID tuner to get a transfer function from real data.
I got this:
Plant1 =
Process model with transfer function:
Kp
G(s) = -------------------------------- * exp(-Td*s)/
(1+2*ZetaTws+(Tw*s)^2)(1+Tp3*s)
Kp = 50.717
Tw = 4.3132
Zeta = 0.63476
Tp3 = 0.10473
Td = 2.521
How do I directly put this into the simulink transferfunction?
You can't, the Transfer Function block is only for linear time invariant models without time delay.
You need to split your transfer function into two parts.
The time delay part exp(-Tds) is implemented using a Transport Delay, where your delay is Td. Note that this gets approximated during simulation (with an accuracy depending on the buffer size of the block) so you won't get exactly 2.521 seconds.
The remaining part of your model is then LTI and as such can be implemented trivially using either one or two Transfer Fcn blocks. (One if you multiply out the numerator terms; two if you want to keep them separate.)
I started to use Simulink and I have a question about changing a transfer function using matlab for loop.
Let say I have the following problem:
And my goal is that "system" will be equal to:
Basically I want to run 5 Simulink simulations from time = 0 to time = 10 for 5 different transfer functions.
Any help is appreciated.
Thank you.
Unless I misunderstood your question, I don't think you need to use Simulink for something like this. The following is my understanding of what you're trying to do, it can be done in plain MATLAB (with the control system toolbox):
t = 0:1e-3:10;
u = ones(size(t));
y = zeros(5,length(t));
for k=1:5
H = (1 + tf('s')*5/k)^k; % system transfer function
CL = 1/((tf('s'))^2*(1-H)); % closed-loop transfer function
y(k,:) = (lsim(CL,u,t))';
end
plot(t,y)
legend('#1','#2','#3','#4','#5','Location','NorthWest')
grid on
xlabel('Time [s]')
ylabel('Output')
which produces the following plot (in Octave). Only the first 2 iterations give a non-zero output:
I am solving a delay differential equation using MATLAB dde23 function. I want to use the output generated by the first dde23 function in the second dde23 function. Here is the code
tspan=[0:1:1440]';
x0=1.7;
%1st function
% options = ddeset('OutputFcn',#odeplot,'OutputSel',1);
sol = dde23(#dd,70,x0,tspan,options);
y_obs=sol.y;
tspan_new=sol.x;
%{2nd function
x1=[x0 ; 0.1; 0.01; 0.01];
final_sol = dde23(#ddc,70,x1,tspan,[],y_obs);
y_fit=final_sol.y;
tdata=final_sol.x;
%}
The time series I generated as an input to the first function is of size 1441 but the size of tspan_new and y_obs is 212 (generated from the dde23 output). I am unable to understand why the size is changing.
Is it possible to output y_obs at each time point provided in the input i.e. is it possible to obtain y_obs of length 1441 in this case ?
Since the size of output is different I am unable to use y_obs vector in my second function. The size of y_fit and tdata is again entirely different from y_obs and tspan.
Unlike the ODE Suite that implements a dense output routine as part of its time march, dde23 requires an explicit post-deval to accomplish what you're after:
tspan=[0:1:1440]';
x0=1.7;
%1st function
sol = dde23(#dd,70,x0,tspan([1,end]),options);
y_obs = deval(sol,tspan);
This function uses local Hermite cubic interpolation on the mesh generated by its dynamic time-stepping routine to approximate the y value at the requested t values.
I am currently doing a project on multimodal biometrics (fusion at score level). So I need to get the score before fusion.
Can anyone tell me how to get the score of the particular test sample using a trained SVM classifier?
I have used the inbuilt svmtrain and svmclassify functions in MATLAB.
Unfortunately the svmclassify function only outputs the label of the class and no distance (score). You will have to write your own classification function. Luckily, this is very easy: As you do have the Statistics Toolbox with svmclassify, you can easily look at the source code of the function with
edit svmclassify
You will see that most of the function is checking inputs etc. The important parts are scaling the data:
sample(:,c) = svmStruct.ScaleData.scaleFactor(c) * ...
(sample(:,c) + svmStruct.ScaleData.shift(c));
and doing the classification using a built-in function svmdecision:
outclass = svmdecision(sample,svmStruct);
From the definition of svmdecision you will see that it outputs the distance f, but svmclassify ignores it. You could therefore easily create a new function, which looks almost exactly like svmclassify, but also returns f:
1 function [outclass,f] = svmclassify(svmStruct,sample, varargin)
...
112 [outclass,f] = svmdecision(sample,svmStruct);
...
158 outclass = []; f = [];
You will find that svmdecision is a private function. To be able to call it from your function, you have to make a copy in your local folder (or any subfolder).
I have a two-column matrix of data obtained from NI-DAQ. The first column is the output data of a motor-generator set (with driver) and the second column is the input data (square wave). I want to find the transfer function using tfest without Simulink. Is it possible? I have System Identification Toolbox.
How can I attach a .mat file to this post? My data on gist https://gist.github.com/anonymous/6484844
You already got the right idea, I don't know where you got stucked.
Here is the code which solves your problem, I tested it, its works fine. Be aware that a simpler input probably gets you better results, that means for example a single step instead of a square wave.
% load your data (text file with your two columns)
load data.txt;
% sample index, reducing of input to get single step instead of square wave
x = 1:1:length(data);
data(x > 2900,:)=[];
x(x > 2900)=[];
% plot data
figure(1)
plot(x,data(:,1)); hold on
plot(x,data(:,2)); hold off
% prepare data for tftest, 100 is a random chosen sampling time
tfdata = iddata(data(:,1),data(:,2),100);
% estimate system, factor 5 -> number of poles (variable as desired)
sys = tfest(tfdata,5);
% plot step response (factor 5 comes from input)
figure(2)
step(5*sys)
Edit: the output for number of poles np=5:
sys =
From input "u1" to output "y1":
-3.337e-05 s^4 + 1.326e-07 s^3 + 1.639e-11 s^2 + 1.221e-14 s + 1.064e-19
----------------------------------------------------------------------------
s^5 + 0.005287 s^4 + 1.516e-06 s^3 + 4.517e-10 s^2 + 2.896e-14 s + 2.037e-19
Edit#2: in your previous question you were asking whether it would be better to use idfrd or iddata - but do you actually have the frequency response data? I actually don't think it should make a big difference, if you choose the number of poles high enough. Just try out what it's working better for you. The workaround is the same.