I have something similar to the following block diagram on Simulink, which looks rather messy especially with an increasing number of blocks.
I want to replace a 3-point summing block with a function block, while keeping the same output.
First I started by placing the code inside the function block:
function y = fcn(u)
sys1 = tf(0.5,[1 0 0 4]);
sys2 = tf([3 0.5],[1 0 15]);
sys3 = tf(1,[1 1]);
y = sys1 + sys2 + sys3;
However I was greeted with an error saying that Simulink does not support code generation.
"The 'tf' class does not support code generation."
I then came across a similar problem here: https://nl.mathworks.com/matlabcentral/answers/74770-is-there-any-way-to-disable-code-generation-in-simulink
I am trying to implement an extrinsic function or 'wrapper function' with some difficulty. I created a new script called myWrapper.m, containing the same code:
function y = myWrapper(u)
sys1 = tf(0.5,[1 0 0 0 4]);
sys2 = tf([3 5],[1 0 15]);
sys3 = tf(1,[1 1]);
y = sys1 + sys2 + sys3;
and the MATLAB Function edited to:
function y1 = fcn(u1)
y1 = myWrapper(u1);
The error persists.
I somehow want to access myWrapper.m file from the MATLAB Function block. Any pointers on how this should be done? Following the previous link given and the official docs I am ending up with something like this in my MATLAB Function block:
function y1 = fcn(u1)coder.extrinsic('myWrapper')
y1 = myWrapper(u1);
The last code above is syntactically incorrect and I am at a loss on how it should be done. MATLAB automaticaly corrects the above code to:
function y1 = fcn(u1,coder,extrinsic, myWrapper )
y1 = myWrapper(u1);
which is not what I want.
Any tips and/or suggestions on how this could be done would be appreciated.
A similar question was asked on the MathWorks forum here, two years ago, with no response.
I was going about tackling this problem completely wrong. Thanks to several helpful comments I realized that in order to replace the summing block, one must NOT remove the Transfer Function blocks which feed into the summing block.
A MATLAB Function does not support code generation (and rightly so) such that a transfer function may be implemented inside it. That is why the blocks simply feed into the MATLAB Function as follows.
The script would very simply be:
function y1 = fcn(u1, u2, u3)
x = (u1 + u2 +u3);
y1 = x;
end
Related
For a project I need to understand a matlab code, but as I am quite new I dont really understand what is happening. I have a function file and a script file.
Function:
function dxdt = sniffer_ode(t,x,par,tu)
X = x(1);
R = x(2);
k1 = par(1);
k2 = par(2);
k3 = par(3);
k4 = par(4);
S = interp1(tu(:,1),tu(:,2),t);
dxdt(1) = k3*S-k4*X;
dxdt(2) = k1*S-k2*X*R;
dxdt = dxdt(:); %dxdt should be column
and the script file:
%sniffer
close all
%initial conditions:
X0=0; R0=0;
x0=[X0 R0];
%parameters:
k1=1; k2=1; k3=1; k4=1;
par=[k1 k2 k3 k4];
%input:
tu=[ 0 , 0
1 , 0
1.01, 1
20 , 1];
[t,x] = ode45(#sniffer_ode,[0 20],x0, [],par,tu);
plot(t,x);
So the question is: What is happening? I also need to plot S in the same figure as X and R. How do I do this?
I appreciate your help!
This is a really basic Matlab question. There is tons of information about your requested topic. I think these slides will help you on the right path.
However, a quick explanation; the first code you provide is the function which describes your ordinary differential equation. This function always has to be of the form x' = f(t,x,...). Herein t is the time and x is the state. After the state (on the place of the dots ...) you can define other input parameters, such as is being done in your ode function. Furthermore, the interp1 function interpolates the data provided.
The second code you provide is the code you start within Matlab. Parameters are defined, after which the ordinary differential equation is solved and plotted.
If you have any further questions I would recommend that you first try to find your answer using a search engine.
I'm working on chapter 8 of A Course in Mathematical Biology. The textbook uses Maple, but includes this link, Computer course of Chapter 8 in Matlab. I'm told to put the following in an m-file:
% defining a recursive function in an m-file
function y = plot_traj(a)
RM = inline('a*x.*exp(-x)', 'a', 'x')
% Note that we are using an inline function. Sometimes it’s easier to do this.
% collecting list of x-coordinates
for i = 1:31,
X(i) = i - 1
end
% collecting list of y-coordinates
for i = 1:30,
Y(i+1)=RM(a,iter(i));
iter(i+1) = Y(i+1);
end
y = plot(X, Y, '*');
Now, save your m-file (as plot traj.m) and close it. Type the following into the command window:
>> plot traj(0.8)
>> plot traj(1.0)
>> plot traj(5.0)
>> plot traj(8.0)
>> plot traj(13.0)
>> plot traj(14.5)
>> plot traj(20.0)
However, when I type plot traj(0.8) into the command window I get this:
>> plot_traj(0.8)
Undefined function or variable "iter".
Error in plot_traj (line 13)
Y(i)=RM(a,iter(i));
I don't see anything wrong with line 13, and I've made sure that my code is exactly what is in the chapter. I've been doing fine with the codes up until this point. I'd appreciate it if anyone could provide some assistance. Thank you.
The problem at line 13 is that the iter local variable array has not been defined. So on the first iteration, the code tries to access iter(1) and fails. I looked at the link you provided and they missed it too. Based on previous examples in the Matlab_Course.pdf (and figure 8.6), the iter array should be initialized as
iter(1) = 1.0;
Just add this line prior to the for loop and you should be good to continue. I suspect also that this line should be added too (again based on the document)
Y(1)=iter(1);
to make sure that both iter and Y have the same length.
Note that it is a good habit to pre-allocate memory to arrays to avoid the internal resizing of matrices/arrays on each iteration of the loop (which can have a negative impact on performance). For this loop
for i = 1:30,
Y(i+1)=RM(a,iter(i));
iter(i+1) = Y(i+1);
end
you can observe that i iterates over 1 through 30, and we always populate Y(i+1) and iter(i+1). So both Y and iter are 31x1 vectors. We can allocate memory to each prior to entering the for loop as
iter = zeros(31,1);
Y = zeros(31,1);
iter(1) = 1;
Y(1) = iter(1);
The same should be done for X as well.
I've created a simple simpson_adaptive method that uses my own simpson method.
My simpson method is correct, but my adaptive method does not seem to work for
integral( sin(2*pi*x)² ) ranging from -1 to 1
The following code represents the adaptive simpson method.
The parameters stand for the function, [a,b] being the interval for the integral and e being the precision.
function I = simpson_adaptief(f,a,b,e)
I1 = simpson(f,a,b,2);
I2 = simpson(f,a,b,4);
if (abs(I1-I2)<e)
I = I2;
else
I = simpson_adaptief(f,a,(a+b)/2,e) + simpson_adaptief(f,(a+b)/2,b,e);
end
end
n here being the amount of parts the function is being split into.
function I = simpson(f,a,b,n)
h = (b-a)/(n);
p=0;
q=0;
for k=1:2:(n-1)
x=a+h*k;
p=p+f(x);
end
for k=2:2:(n-1)
x=a+h*k;
q=q+f(x);
end
I = h/3*(f(a)+f(b)+4*p+2*q);
end
Do you guys have any suggestions on what the possible cause of the problem could be?
Other functions seem to work.
EDIT: I think it has something to do with my if abs(I1-I2)<e. When I change it to abs(I1-I2)>e, it works, as my program then does the recursion step first.
Thanks in advance!
I'm pretty new to matlab, but is it possible to call for the function you are creating inside that same function file? That is what I see in your simpson_adaptief function
I wrote some code that works just fine to evaluate theta on its own with some test input. However, I would like to take this code and turn it into a function that I can call within another matlab file. I keep getting the error message, "Function definitions are not permitted in this context."
I want to be able to define four vectors in another matlab file and call SP1 to evaluate theta for those inputs. I'm not sure where I'm going wrong, though. Please help!
Thanks so much.
clc
clear all
function theta = SP1(p,q1,w1,r)
% INPUT:
%function theta = SP1(p,q1,w1,r)
% p = [5; -7; 12];
% q1 = [17.3037; -3.1128; 2.48175];
% w1 = [1/sqrt(8); sqrt(3/8); 1/sqrt(2)];
% r = [1; 2; -3];
% Define vectors u and v as well as u' and v'.
u = p - r;
v = q1 - r;
w1_t = transpose(w1);
u_prime = u - w1 * w1_t * u;
v_prime = v - w1 * w1_t * v;
% Calculate theta if conditions are met for a solution to exist.
if (abs(norm(u_prime)-norm(v_prime))<0.01) & (abs((w1_t * u)-(w1_t * v))<0.01)
X = w1_t*cross(u_prime,v_prime);
Y = dot(u_prime,v_prime);
theta = atan2(X,Y)
else if (norm(u_prime) == 0 | norm(v_prime) == 0)
disp('Infinite Number of Solutions')
else
disp('Conditions not satisfied to find a solution')
end
end
I think you can just remove the top two lines,
clc
clear all
and save the rest of the code starting with function as SP1.m file.
Then you should be able to call this function as SP1 from other m files.
I think you're confused about how functions work. The first line of a function definition defines how many inputs and outputs MATLAB expects:
function theta = SP1(p,q1,w1,r)
This means that calling a function SP1 will require you to give four inputs, and will return one output. It doesn't mean that:
Your inputs need to be named p, q1 and so on
Your output will be called theta automatically
The function will automatically take in the input variables p, q1, etc if they exist in the workspace.
It also doesn't do any checking on the inputs; so if you require that inputs be of a certain type, size, etc. you need to write your own error checking at the start of the file. You might intend that those inputs be 3x1 vectors, but there's nothing in the function to tell MATLAB that. So, SP1(1,2,3,4) will work, to some extent - it will take those inputs and try to run them through the function, and if they don't cause an error it will give you an output. The output might be wrong, but the computer doesn't know that.
Once you have a function you can call it multiple ways from the command line or from within other functions or scripts. As previously mentioned you don't have to stick to the naming of variables within the function, as long as input variables exist when the function is called MATLAB will accept them:
theta = SP1(p8,q27,w35,not_r);
myoutput = SP1(any,variable,I,like);
I don't necessarily have to give an output (but then the first output will be routed to ans)
SP1(this,will,also,work);
If I have some variables stored in a *.mat file (the case you seem to be asking about), I can do it like this:
load('mydata.mat'); %this file contains stored variables p, q1, w1 and r
theta = SP1(p,q1,w1,r);
The code in question is here:
function k = whileloop(odefun,args)
...
while (sign(costheta) == originalsign)
y=y(:) + odefun(0,y(:),vars,param)*(dt); % Line 4
costheta = dot(y-normpt,normvec);
k = k + 1;
end
...
end
and to clarify, odefun is F1.m, an m-file of mine. I pass it into the function that contains this while-loop. It's something like whileloop(#F1,args). Line 4 in the code-block above is the Euler method.
The reason I'm using a while-loop is because I want to trigger upon the vector "y" crossing a plane defined by a point, "normpt", and the vector normal to the plane, "normvec".
Is there an easy change to this code that will speed it up dramatically? Should I attempt learning how to make mex files instead (for a speed increase)?
Edit:
Here is a rushed attempt at an example of what one could try to test with. I have not debugged this. It is to give you an idea:
%Save the following 3 lines in an m-file named "F1.m"
function ydot = F1(placeholder1,y,placeholder2,placeholder3)
ydot = y/10;
end
%Run the following:
dt = 1.5e-12 %I do not know about this. You will have to experiment.
y0 = [.1,.1,.1];
normpt = [3,3,3];
normvec = [1,1,1];
originalsign = sign(dot(y0-normpt,normvec));
costheta = originalsign;
y = y0;
k = 0;
while (sign(costheta) == originalsign)
y=y(:) + F1(0,y(:),0,0)*(dt); % Line 4
costheta = dot(y-normpt,normvec);
k = k + 1;
end
disp(k);
dt should be sufficiently small that it takes hundreds of thousands of iterations to trigger.
Assume I must use the Euler method. I have a stochastic differential equation with state-dependent noise if you are curious as to why I tell you to take such an assumption.
I would focus on your actual ODE integration. The fewer steps you have to take, the faster the loop will run. I would only worry about the speed of the sign check after you've optimized the actual integration method.
It looks like you're using the first-order explicit Euler method. Have you tried a higher-order integrator or an implicit method? Often you can increase the time step significantly.