Online polynomial curve fitting in Simulink - matlab

How to fit curves in Simulink and still generate the code?
I have a model of a sensor in Simulink, that returns vectors Pos_x and Pos_y. Each vector has size of 20x1, and their values change every one step time (1ms).
I am trying to calculate the coeffecients of the 3rd degree Polynomial y(x) = p1*x^3 + p2*x^2 + p3*x + p4 in Simulink, that fits the data.
I did not find any block in simulink that calculates the coeffecients, so I used a simple Matlab function
function [p1, p2, p3, p4] = fcn(x,y)
% f(x) = p1*x^3 + p2*x^2 + p3*x + p4
f = fit(x', y', 'Poly3'); % I have also tried "polyfit"
p1 = f.p1;
p2 = f.p2;
p3 = f.p3;
p4 = f.p4;
end
but I get the error:
Function 'fit' not supported for code generation.
1- so back to my qustion, How to fit curves in Simulink and still generate the code?
2- I am also open to any other suggestion

If possible, you can use directly the LSQCURVEFIT function using Levenberg-Marquardt - method, which is Coder-compatible, with some limitations - see it's documentation that describes the limitations in detail.
Under the hood FIT uses LSQCURVEFIT, but in a non-Coder-compatible way.

Related

How to best-fit a rational function approximation to Theodorsen's function using the lsqcurvefit function in Matlab?

I am using a rational function (polynomial ratio) to approximate Theodorsen's function. I am having issues in guessing the correct (most optimal) initial guess parameters using the lsqcurvefit function in Matlab. Is there a way to know what would be the best initial guess parameters to get the best fit result?
My code is the following:
k = logspace(-10,1,300);
% Exact Theodorsen's Function C(k) in terms of Bessel Function
Ck= #(k)(besselh(1,2,k))./(besselh(1,2,k)+1i*besselh(0,2,k));
% Ckget function used to extract real and imaginary numbers and stacks the result
Ckget= #(k)[real(Ck(k)); imag(Ck(k))];
% Define 3rd order approximation function
x0= [.1,.1,.1,1,.1,.1,.1,.1]; % Create initial guess
U = 200;
b = 3;
s = 1i*k*(U/b);
Ck2 = #(x,k)((x(1)*s.^3 + x(2)*s.^2 + x(3)*s + x(4))./(x(5)*s.^3 + x(6)*s.^2 + x(7)*s + x(8)));
Ck2get= #(x,k)[real(Ck2(x,k)); imag(Ck2(x,k))]; %extract real & imaginary values
% Use curve fit function for best fit approximation
x2= lsqcurvefit(Ck2get,x0,k,Ckget(k))

Get the points from a MatLab fit object plot

I am a Matlab amateur so please bear with me -
I currently use Matlab to fit a complex equation to two-dimensional data. Right now I have a program which uses f = fit(xdata, ydata, function, options) to generate a fit object.
I can then use confint(f) and f.parameter etc. to get the fitted coefficients and confidence intervals, and I can use plot(f,x,y) to make a plot of the data and the fit.
From that point on the only way I know how to get the points which were plotted is to use the brush(?) tool and select all of the line, then copy the data to clipboard and paste it into excel or some such thing. I would much rather get those points directly from Matlab, perhaps into an array, but I have no idea how.
Can any MatLab veteran tell me if what I want is even possible? It would be very difficult due to the complexity of my equation to plot those points myself, but I will if need be (it can take ~30 minutes to do this fit and my computer is no slouch).
Since you have not shared any code or data, I use an example from MATLAB documentation:
load franke
f = fit([x, y],z,'poly23');
plot(f,[x,y],z)
So as you can sew, it first loads a dataset including x,y,z vectors. Then fits a surface to the data using 'poly23'. In your case it can be different sets of vectors and function and still as you said you will get the f function.
Now we can take a look at the function f
>> f
Linear model Poly23:
f(x,y) = p00 + p10*x + p01*y + p20*x^2 + p11*x*y + p02*y^2 + p21*x^2*y
+ p12*x*y^2 + p03*y^3
Coefficients (with 95% confidence bounds):
p00 = 1.118 (0.9149, 1.321)
p10 = -0.0002941 (-0.000502, -8.623e-05)
p01 = 1.533 (0.7032, 2.364)
p20 = -1.966e-08 (-7.084e-08, 3.152e-08)
p11 = 0.0003427 (-0.0001009, 0.0007863)
p02 = -6.951 (-8.421, -5.481)
p21 = 9.563e-08 (6.276e-09, 1.85e-07)
p12 = -0.0004401 (-0.0007082, -0.0001721)
p03 = 4.999 (4.082, 5.917)
It shows you the form of the function and the coefficients. So you can use it as follows:
zz = f(x,y);
To make sure you can plot the data again:
figure;
scatter3(x,y,zz,'.k');
hold on
scatter3(x,y,z,'.');
When you call f = fit(xdata, ydata, function, options), function name decides the equation. See list of official equations.
Simply iterate through data points and compute results using corresponding polynomial. So in your case lets say if function=poly2 you'll be doing computation as follows:
#Fit your data
f = fit([xdata, ydata],'poly2');
#Print name of coefficients (Just for Verification)
coeffnames(f)
#Fetch values of coefficients like p1, p2, ...
p = coeffvalues(c)
#Compute output points from min(xdata) to max(xdata) spaced at deltaX
deltaX = 0.1;
x = [min(xdata):deltaX:max(xdata)];
Y = p(1)*x^2+p(2)*x+p(3); #This is equation for function
I understand there can be alternate complex Java code to iterate through objects on a matlab figure and plot its value but using equations is a quick and valid approach.

how do i plot hysteresis using matlab?

I want to model memristor using its equation in exponential mode using Matlab . My aim is to just get the hysteresis plot(i-v plot) in Matlab. the equation is like
i=x^n*b*sinh(av)+m(exp(gv)-1)
x'=Af(x)h(v)
where f(x) is window function and h(v) is polynomial function, A is constant.
f(x)=1-(2x-1)^2
h(v)=cv+dv^3;
c and d are constant c<0 & d>0
a=2; b=0.01; g=4; n=4; A=25; m=0.001;
x is internal state of device..is it possible to get plot in matlab?
I have tried in matlab it is showing errors
This script I found on google after a very brief search:
http://webee.technion.ac.il/people/skva/Memristor%20Models/MATLAB/memristor.m
You can choose there what kind of model do you want to use (Nonlinear Ion Drift model in your case), the type of window function (yours is Jogelkar's I assume) and nonlinear voltage-current relation.
After modifying a bit their script you should get something like this:
b=0.01; g=4; n=4; a=2;A=25; m=0.001;
c=-1;d=4;%your constants
numOfPoints = 10000;
t = linspace(-1, 1,numOfPoints);
dt = t(2) - t(1);
volt = .003*sin(2*pi*t);
x = zeros(size(t));
curr = x;
for i=2:numOfPoints
x(i) = x(i-1) + A*(c*volt(i)+d*(volt(i))^3)*(1-(2*x(i-1)-1)^2)*dt;
curr(i)=x(i)^n*b*sinh(a*volt(i))+m*(exp(g*volt(i))-1);
end;
fig = figure(1);
plot(volt,curr);
xlabel('Voltage');ylabel('Current');
figure(fig);
Good luck!

Exponential Curve Fitting in Matlab

I have a data-set which is loaded into matlab. I need to do exponential fitting for the plotted curve without using the curve fitting tool cftool.
I want to do this manually through executing a code/function that will output the values of a and b corresponding to the equation:
y = a*exp(b*x)
Then be using those values, I will do error optimization and create the best fit for the data I have.
Any help please?
Thanks in advance.
Try this...
f = fit(x,y,'exp1');
I think the typical objective in this type of assignment is to recognize that by taking the log of both sides, various methods of polynomial fit approaches can be used.
ln(y) = ln(a) + ln( exp(x).^b )
ln(y) = ln(a) + b * ln( exp(x) )
There can be difficulties with this approach when errors such as noise are involved due to the behavior of ln as it approaches zero.
In this exercise I have a set of data that present an exponential curve and I want to fit them exponentially and get the values of a and b. I used the following code and it worked with the data I have.
"trail.m" file:
%defining the data used
load trialforfitting.txt;
xdata= trialforfitting(:,1);
ydata= trialforfitting(:,2);
%calling the "fitcurvedemo" function
[estimates, model] = fitcurvedemo(xdata,ydata)
disp(sse);
plot(xdata, ydata, 'o'); %Data curve
hold on
[sse, FittedCurve] = model(estimates);
plot(xdata, FittedCurve, 'r')%Fitted curve
xlabel('Voltage (V)')
ylabel('Current (A)')
title('Exponential Fitting to IV curves');
legend('data', ['Fitting'])
hold off
"fitcurvedemo.m" file:
function [estimates, model] = fitcurvedemo(xdata, ydata)
%Call fminsearch with a random starting point.
start_point = rand(1, 2);
model = #expfun;
estimates = fminsearch(model, start_point);
%"expfun" accepts curve parameters as inputs, and outputs
%the sum of squares error [sse] expfun is a function handle;
%a value that contains a matlab object methods and the constructor
%"FMINSEARCH" only needs sse
%estimate returns the value of A and lambda
%model computes the exponential function
function [sse, FittedCurve] = expfun(params)
A = params(1);
lambda = params(2);
%exponential function model to fit
FittedCurve = A .* exp(lambda * xdata);
ErrorVector = FittedCurve - ydata;
%output of the expfun function [sum of squares of error]
sse = sum(ErrorVector .^ 2);
end
end
I have a new set of data that doesn't work with this code and give the appropriate exponential fit for the data curve plotted.

ODE solver of a system with adaptive law

I have an unknown non-linear system and I want to model it using another system with some adaptable parameters (for instance, a neural network). So, I want to fix an online learning structure of the unknown system without knowing its dynamics, I can only interact with it through inputs-outputs. My problem is that I can not make it work in MATLAB using ode solvers. Lets say that we have this real system (my actual system is more complicated, but I will give a simple example in order to be understood):
function dx = realsystem(t, x)
u = 2;
dx = -3*x+6*u;
end
and we solve the equations like this:
[t,x_real] = ode15s(#(t,x)realsystem(t,x), [0 1], 0)
We suppose that is an unknown system and we do not know the coefficients 3 and 6 so we take an adaptive system with the 2 adaptive laws:
dx(t) = -p1(t)*x(t) + p2(t)*u(t)
dp1(t) = -e(t)*x(t)
dp2(t) = e(t)*u(t)
with e(t) the error e(t) = x(t) - x_real(t).
The thing is that I cannot find a way to feed the real values for each t to the ode solver in order to have online learning.
I tried with something like this but it didn't work:
function dx = adaptivesystem(t, x, x_real)
dx = zeros(3,1);
e = x_real - x;
u = 2;
dx(1) = -x(2)*x(1)+x(3)*u;
dx(2) = -e*x(1); %dx(2) = dp1(t)
dx(3) = e*u; %dx(3) = dp2(t)
end
You should be aware that your problem is ill-posed as it is. Given any trajectory x(t) obtained via sampling and smoothing/interpolating, you can choose p1(t) at will and set
p2(t) = ( x'(t) - p1(t)*x(t) ) / u.
So you have to formulate restrictions. One obvious is that the functions p1 and p2 should be valid for all trajectories of the black-box system. Do you have different trajectories available?
Another variant is to demand that p1 and p2 are constants. Actually, in this case and if you have equally spaced samples available, it would be easier to first find a good difference equation for the data. With the samples x[n] for time t[n]=t0+n*dt form a matrix X with rows
[ -u, x[n], x[n+1], ... ,x[n+k] ] for n=0, ... , N-k
and apply QR decomposition or SVD to X to determine the right hand kernel vectors. QR may fail to show a usable rank deficiency, so use the SVD on the top square part of R = USV^T, S diagonal, ordered as usual, U,V square and orthogonal, and use the last row of V, with coefficients
[b, a[0], ..., a[k] ],
corresponding to the smallest eigenvalue, to form the difference equation
a[0]*x[n]+a[1]*x[n-1]+...+a[k]*x[n-k]=b*u.
If the effective rank of R resp. S is not (k-1), then reduce k to be the effective rank plus one and start again.
If in the end k=1 is found, then you can make a differential equation out of it. Reformulate the difference equation as
a[0]*(x[n]-x[n-1])/dt = -(a[0]+a[1])/dt * x[n-1] + b/dt * u
and read off the differential equation
x'(t) = -(a[0]+a[1])/(a[0]*dt) * x(t) + b/(a[0]*dt) * u
One may reject this equation if the coefficients become uncomfortably large.