I'm having some trouble with the function "lsqnonlin" on Matlab. I'm trying to optimize a PID controller inside Arduino by using this function that has the coefficients (Kp,Ki,Kd) of the PID as decisional variables and the goal function is to minimize the least-square difference of the response minus the reference value.
This link explains better what I'm doing: http://it.mathworks.com/help/optim/ug/lsqnonlin-with-a-simulink-model.html.
The difference between that example and my problem is that I want to perform a sort of Hardware-In-The-Loop simulation, replacing the simulation performed by Simulink with the actual system that I designed, on which a sensor interfaced with Arduino provides the response "yout" to Matlab by Serial Communication.
The problem is that the algorithm on Matlab changes the variables (Kp,Ki,Kd) with a really small step (10^-8 or something like that) and so I can't see any change on the actual response. After a few iterations the algorithm stops saying: "lsqnonlin stopped because the size of the current step is less than
the selected value of the step size tolerance".
I can't understand why the steps are so little and why it stops like that. My code is the following.
pid0 = [10 0 0]; %inizialization of PID parameters
options = optimset('LargeScale','off','Display','iter',...
'TolX',0.001,'TolFun',0.001);
pid = lsqnonlin(#trackpid, pid0, [0 0 0], [], options)
Kp = pid(1); Ki = pid(2); Kd = pid(3);
The trackpid function is:
function F = trackpid(pid)
% Serial communication
s = serial('/dev/cu.usbmodemFD131');
set(s,'BaudRate', 9600);
set(s,'DataBits', 8);
set(s,'StopBits', 1);
% Global Variables
numberOfDatas = 700;
Kp = pid(1)
Ki = pid(2)
Kd = pid(3)
i = 1;
fopen(s);
pause(1.7); %i need to wait 1.7s in order to read the values
%Send to Arduino the PID coefficients
fprintf(s,num2str(Kp));
fprintf(s,num2str(Ki));
fprintf(s,num2str(Kd));
while (fscanf(s,'%c') ~= 't') %Wait for Arduino to start the simulation
end
%Scan
while(i <= numberOfDatas)
yout(i) = fscanf(s,'%f');
i = i + 1;
end
fclose(s);
yout
F = yout - 21; %evaluate the difference between the response and the reference
Thank you in advance.
Related
I've implement a moving maximum filter in matlab and now I have to determine if it's LTI or not. I've already prove it's linear but I can't prove if it's time ivnariant. To prove this I have to give as an input a signal x[n] and get the output X[n]. After that I'm giving the same signal but this time it have to delay it that is x[n-a] and the output must be X[n-a] the same as the X[n] but delayed. My problem is that I don't know what input to give. Also, the moving maximum is a LTI system or not?
Thanks in advance.
Max-Filter Using For-Loop and Testing System for Linear and Time-Invariance
Filter Construction:
To filter an array/matrix/signal a for-loop can be applied. Within this for-loop, portions of the signal that overlaps the window must be stored in this case called Window_Sample. To apply the maximum filter the max() of the Window_Sample must be taken upon each iteration of the loop. Upon each iteration of the loop the window moves. Here I push all the code that calculates the maximum filtered signal into a function called Max_Filter().
Time-Invariant or Not-Time Invariant:
With proper padding, I think the maximum filter is time-invariant/shift-invariant. Concatenating zeros to the start and ends of the signal is a good way to combat this. The amount of padding I used on each end is the size of the window, the requirement would be half the window but there's no harm in having a little bit of buffer. Unfortunately, without proper padding, this may appear to break down in MATLAB since the max filter will be introduced to points early. In this case without padding the ramp the max filter will take the 5th point as the max right away. Here you can apply a scaling factor to test if the system is linear. You'll see that the system is not linear since the output is not a scaled version of the input.
clf;
%**********************************************************%
%ADJUSTABLE PARAMETERS%
%**********************************************************%
Window_Size = 3; %Window size for filter%
Delay_Size = 5; %Delay for the second test signal%
Scaling_Factor = 1; %Scaling factor for the second test signal%
n = (0:10);
%Ramp function with padding%
Signal = n; %Function for test signal%
%**********************************************************%
Signal = [zeros(1,Window_Size) Signal zeros(1,Window_Size)];
Filtered_Result_1 = Max_Filter(Signal,Window_Size);
%Ramp function with additional delay%
Delayed_Signal = Scaling_Factor.*[zeros(1,Delay_Size) Signal];
Filtered_Result_2 = Max_Filter(Delayed_Signal,Window_Size);
plot(Filtered_Result_1);
hold on
plot(Filtered_Result_2);
xlabel("Samples [n]"); ylabel("Amplitude");
title("Moving Maximum Filtering Signal");
legend("Original Signal","Delayed Signal");
xticks([0: 1: length(Filtered_Result_2)]);
xlim([0 length(Filtered_Result_2)]);
grid;
function [Filtered_Signal] = Max_Filter(Signal,Filter_Size)
%Initilizing an array to store filtered signal%
Filtered_Signal = zeros(1,length(Signal));
%Filtering array using for-loop and acccesing chunks%
for Sample_Index = 1: length(Signal)
Start_Of_Window = Sample_Index - floor(Filter_Size/2);
End_Of_Window = Sample_Index + floor(Filter_Size/2);
if Start_Of_Window < 1
Start_Of_Window = 1;
end
if End_Of_Window > length(Signal)
End_Of_Window = length(Signal);
end
Window_Sample = Signal(Start_Of_Window:End_Of_Window);
Filtered_Signal(1,Sample_Index) = max(Window_Sample);
end
end
Alternatively Using Built-In Functions:
To test the results of the created filter it is a good idea to compare this to the output results of MATLAB's built-in function movmax(). Here the results appear to be the same as the for-loop implementation.
clf;
Window_Size = 3;
n = (0:10);
%Ramp function with padding%
Signal = n;
Signal = [zeros(1,Window_Size) Signal zeros(1,Window_Size)];
Filtered_Result_1 = movmax(Signal,Window_Size);
%Ramp function with additional delay%
Delay_Size = 5;
Delayed_Signal = [zeros(1,Delay_Size) Signal];
Filtered_Result_2 = movmax(Delayed_Signal,Window_Size);
plot(Filtered_Result_1);
hold on
plot(Filtered_Result_2);
xlabel("Samples [n]"); ylabel("Amplitude");
title("Moving Maximum Filtering Signal");
legend("Original Signal","Delayed Signal");
xticks([0: 1: length(Filtered_Result_2)]);
xlim([0 length(Filtered_Result_2)]);
grid;
Ran using MATLAB R2019b
This post builds on my post about quickly evaluating analytic Jacobian in Matlab:
fast evaluation of analytical jacobian in MATLAB
The key difference is that now, I am working with the Hessian and I have to evaluate close to 700 matlabFunctions (instead of 1 matlabFunction, like I did for the Jacobian) each time the hessian is evaluated. So there is an opportunity to do things a little differently.
I have tried to do this two ways so far and I am thinking about implementing a third and was wondering if anyone has any other suggestions. I will go through each method with a toy example, but first some preprocessing to generate these matlabFunctions:
PreProcessing:
% This part of the code is calculated once, it is not the issue
dvs = 5;
X=sym('X',[dvs,1]);
num = dvs - 1; % number of constraints
% multiple functions
for k = 1:num
f1(X(k+1),X(k)) = (X(k+1)^3 - X(k)^2*k^2);
c(k) = f1;
end
gradc = jacobian(c,X).'; % .' performs transpose
parfor k = 1:num
hessc{k} = jacobian(gradc(:,k),X);
end
parfor k = 1:num
hess_name = strcat('hessian_',num2str(k));
matlabFunction(hessc{k},'file',hess_name,'vars',X);
end
METHOD #1 : Evaluate functions in series
%% Now we use the functions to run an "optimization." Just for an example the "optimization" is just a for loop
fprintf('This is test A, where the functions are evaluated in series!\n');
tic
for q = 1:10
x_dv = rand(dvs,1); % these are the design variables
lambda = rand(num,1); % these are the lagrange multipliers
x_dv_cell = num2cell(x_dv); % for passing large design variables
for k = 1:num
hess_name = strcat('hessian_',num2str(k));
function_handle = str2func(hess_name);
H_temp(:,:,k) = lambda(k)*function_handle(x_dv_cell{:});
end
H = sum(H_temp,3);
end
fprintf('The time for test A was:\n')
toc
METHOD # 2: Evaluate functions in parallel
%% Try to run a parfor loop
fprintf('This is test B, where the functions are evaluated in parallel!\n');
tic
for q = 1:10
x_dv = rand(dvs,1); % these are the design variables
lambda = rand(num,1); % these are the lagrange multipliers
x_dv_cell = num2cell(x_dv); % for passing large design variables
parfor k = 1:num
hess_name = strcat('hessian_',num2str(k));
function_handle = str2func(hess_name);
H_temp(:,:,k) = lambda(k)*function_handle(x_dv_cell{:});
end
H = sum(H_temp,3);
end
fprintf('The time for test B was:\n')
toc
RESULTS:
METHOD #1 = 0.008691 seconds
METHOD #2 = 0.464786 seconds
DISCUSSION of RESULTS
This result makes sense because, the functions evaluate very quickly and running them in parallel waists a lot of time setting up and sending out the jobs to the different Matlabs ( and then getting the data back from them). I see the same result on my actual problem.
METHOD # 3: Evaluating the functions using the GPU
I have not tried this yet, but I am interested to see what the performance difference is. I am not yet familiar with doing this in Matlab and will add it once I am done.
Any other thoughts? Comments? Thanks!
%-------------------------------------------------------------------
% Function to Generate ECG of 1 heart beat signal
function [Heartbeat,t1] = ECG_Gen (HR,pulse_width,Amp)
Fs = 48000;
delay = ((60/HR)/2)-(0.5*pulse_width);
t1 = -delay:(1/Fs):delay;
Heartbeat = Amp*tripuls (t1,pulse_width);
%-------------------------------------------------------------------
%Test Circuit configuration
function [FECG_MECG,Mixed_ECG,fastTime] = Test_Circuit (FHR,MHR)
Fs = 48000;
%FHR = 150;
%MHR = 60;
Fpulse_width = 30e-3;
Mpulse_width = 60e-3;
FAmp = 0.2;
MAmp = 0.5;
% Fetal ECG Gen
%------------------------------------------------
[FECG,FHR_Delay]= ECG_Gen (FHR,Fpulse_width,FAmp);
% Maternal ECG Gen
%------------------------------------------------
[MECG,MHR_Delay]= ECG_Gen (MHR,Mpulse_width,MAmp);
% Composite signal implementation
%------------------------------------------------
% Set parameters for Composite signal Algorithms
if length (MECG) > length (FECG) % Check for time sequences for both ECG signal
slowECG = FECG; % Set interpolation to slower rate
fastECG = MECG;
timeSeg = length(MECG);
fastTime = MHR_Delay; % Set sampling times
slowTime = FHR_Delay;
else
slowECG = MECG;
fastECG = FECG;
timeSeg = length(FECG);
fastTime = FHR_Delay;
slowTime = MHR_Delay;
end
FECG_MECG = zeros (timeSeg,2); % To hold stereo output
FECG_MECG(:,2) = fastECG(1,:); % Assign higher rate signal to one channel
% Interpolation on the slower rater sampled ECG
slowECGInterp = interp1 (slowTime,slowECG,fastTime);
slowECG = num2cell(slowECGInterp); % Conversion to cell Array in order to remove NaN
slowECG(cellfun(#(slowECG) any(isnan(slowECG)),slowECG)) = [];
slowECG = cell2mat(slowECG);
j = 1;
for i = 1:timeSeg
FECG_MECG(i,1) = slowECG(1,j);
if j == length(slowECG)
j = 0;
end
j = j+1;
end
Mixed_ECG = FECG_MECG(:,1) + FECG_MECG(:,2); % to hold mono output
%while (1)
%sound(Mixed_ECG ,Fs);
%end
%-------------------------------------------------------------------
% Test Wave script
clear all
%clc
clc
Fs = 48000;
%for i = 1:3
%toc
MHR = 60;
FHR = 200;
% Obtain ECG interpolated signal and composite
[FECG_MECG,Mixed_ECG,fastTime] = Test_Circuit (FHR,MHR);
% for test purposes
[MECG,MHR_Delay]= ECG_Gen (60,60e-3,0.5);
%t = timer ('TimerFcn','stat=false','Period',2.0);
wavwrite (FECG_MECG(:,2),Fs,'ECGwav.wav');
i = 0;
a = 1;
tic
while (1)
while (toc < 20*a)
sound (MECG,Fs);
end
toc
a = a+1;
[MECG,MHR_Delay]= ECG_Gen (60*a,60e-3,0.5);
if a > 4
break
end
end
%start(t)
%tic
%t = cputime;
%y = wavread('ECGwav.wav');
%while (1)
% sound(y,Fs);
%end
%toc
Hey Thank you very much for getting back to me, I have made use of your interpolation but still have minor problems from the reading obtained from the Monitor. Fist of all, say I have a constant signal with fixed time period say, 0.8s and I want to add composite signal of say 0.3s, I have managed to use your interpolation method to sample the 0.3s signal at the rate of my 0.8s signal. I think I have solved this issue. Second issue deals with how to combine the two signals which I have managed to do somehow but when I use a while loop in order to repeat the composite signal say over 20s, the signals obtained from the sound output isn't quite what I expected since its sounding the array of stored composite signal which contain ( signal with 0.8s = slowInterp signal of 0.3s ). I have include all the codes and functions. Basically, I need the sound output in while loop to sync with the composite signal for example: if I have a signal that repeats every 1s, I would expect to hear a beep in a while loop that runs for 10s to produce 10 beeps, etc
It is hard to tell exactly what you need, but probably doing interpolation on the sequence that is sampled at the slower rate would work for your application.
If t1s are your times from your faster sequence, and t2s are times from your slower sequence, and slow is your slower sequence then do:
slowInterp = interp1(t2s, slow, t1s);
now you will have the sequency slow sampled at the faster rate.
This is only useful for displaying the time series. If you are doing any spectral analysis, this will introduce artifacts, but that is a more advanced topic.
Using the resample function in the signal processing toolbox could also be useful.
I'm having trouble getting consistent results with the code I am using. I want to run my Arduino for a specific amount of time (say 20 seconds) and collect data from the analog pin with a specific sampling rate (say four samples a second). The code is as follows.
a_pin = 0;
tic;
i = 0;
while toc < 20
i = i + 1;
time(i) = toc;
v(i) = a.analogRead(a_pin);
pause(.25);
end
Is there a way to set the loop to run a specific time and then in the loop sample at a different rate?
You can try this:
a_pin = 0;
fs = 4; % sampling frequency (samplings per second)
mt = 20; % time for measurements
ind = 1;
nind = 1;
last_beep = 0;
tic;
while toc < mt
time(ind) = toc;
v(ind) = a.analogRead(a_pin);
% wait for appropriate time for next measurement
while( nind == ind )
nind = floor(toc*fs) + 1;
end
ind = nind;
% beep every second
if (ceil(toc) > last_beep)
beep(); % don't know if this one exist, check docs
last_beep = ceil(toc);
end
end
Maximal sampling time for a single Arduino analog read command is around 0.04 s, in practice I'd go minimally 0.05. Adding two read operations is in the order of 2*0.04, in practice more like 0.1 s. I think it is mainly limited by the USB communication speeds.
I am also new at arduino, but having implemented a real time analysis for EEG using it, on practice, I was able to sample 2 analog channels with a samplinf frequency between 57 and 108Hz. It was very variable (calculated through tic/toc), but it is still proper for realtime processing in my case.
My code uses a While loop, a series of memory updates, digital pin manipulations, plot of trace (drawnow) and seems to run smoothly enough
My answer is simply here : 0.0283 sec for sampling 2 analog inputs in my case.
Cheers
I am coding a perceptron to learn to categorize gender in pictures of faces. I am very very new to MATLAB, so I need a lot of help. I have a few questions:
I am trying to code for a function:
function [y] = testset(x,w)
%y = sign(sigma(x*w-threshold))
where y is the predicted results, x is the training/testing set put in as a very large matrix, and w is weight on the equation. The part after the % is what I am trying to write, but I do not know how to write this in MATLAB code. Any ideas out there?
I am trying to code a second function:
function [err] = testerror(x,w,y)
%err = sigma(max(0,-w*x*y))
w, x, and y have the same values as stated above, and err is my function of error, which I am trying to minimize through the steps of the perceptron.
I am trying to create a step in my perceptron to lower the percent of error by using gradient descent on my original equation. Does anyone know how I can increment w using gradient descent in order to minimize the error function using an if then statement?
I can put up the code I have up till now if that would help you answer these questions.
Thank you!
edit--------------------------
OK, so I am still working on the code for this, and would like to put it up when I have something more complete. My biggest question right now is:
I have the following function:
function [y] = testset(x,w)
y = sign(sum(x*w-threshold))
Now I know that I am supposed to put a threshold in, but cannot figure out what I am supposed to put in as the threshold! any ideas out there?
edit----------------------------
this is what I have so far. Changes still need to be made to it, but I would appreciate input, especially regarding structure, and advice for making the changes that need to be made!
function [y] = Perceptron_Aviva(X,w)
y = sign(sum(X*w-1));
end
function [err] = testerror(X,w,y)
err = sum(max(0,-w*X*y));
end
%function [w] = perceptron(X,Y,w_init)
%w = w_init;
%end
%------------------------------
% input samples
X = X_train;
% output class [-1,+1];
Y = y_train;
% init weigth vector
w_init = zeros(size(X,1));
w = w_init;
%---------------------------------------------
loopcounter = 0
while abs(err) > 0.1 && loopcounter < 100
for j=1:size(X,1)
approx_y(j) = Perceptron_Aviva(X(j),w(j))
err = testerror(X(j),w(j),approx_y(j))
if err > 0 %wrong (structure is correct, test is wrong)
w(j) = w(j) - 0.1 %wrong
elseif err < 0 %wrong
w(j) = w(j) + 0.1 %wrong
end
% -----------
% if sign(w'*X(:,j)) ~= Y(j) %wrong decision?
% w = w + X(:,j) * Y(j); %then add (or subtract) this point to w
end
you can read this question I did some time ago.
I uses a matlab code and a function perceptron
function [w] = perceptron(X,Y,w_init)
w = w_init;
for iteration = 1 : 100 %<- in practice, use some stopping criterion!
for ii = 1 : size(X,2) %cycle through training set
if sign(w'*X(:,ii)) ~= Y(ii) %wrong decision?
w = w + X(:,ii) * Y(ii); %then add (or subtract) this point to w
end
end
sum(sign(w'*X)~=Y)/size(X,2) %show misclassification rate
end
and it is called from code (#Itamar Katz) like (random data):
% input samples
X1=[rand(1,100);rand(1,100);ones(1,100)]; % class '+1'
X2=[rand(1,100);1+rand(1,100);ones(1,100)]; % class '-1'
X=[X1,X2];
% output class [-1,+1];
Y=[-ones(1,100),ones(1,100)];
% init weigth vector
w=[.5 .5 .5]';
% call perceptron
wtag=perceptron(X,Y,w);
% predict
ytag=wtag'*X;
% plot prediction over origianl data
figure;hold on
plot(X1(1,:),X1(2,:),'b.')
plot(X2(1,:),X2(2,:),'r.')
plot(X(1,ytag<0),X(2,ytag<0),'bo')
plot(X(1,ytag>0),X(2,ytag>0),'ro')
legend('class -1','class +1','pred -1','pred +1')
I guess this can give you an idea to make the functions you described.
To the error compare the expected result with the real result (class)
Assume your dataset is X, the datapoins, and Y, the labels of the classes.
f=newp(X,Y)
creates a perceptron.
If you want to create an MLP then:
f=newff(X,Y,NN)
where NN is the network architecture, i.e. an array that designates the number of neurons at each hidden layer. For example
NN=[5 3 2]
will correspond to an network with 5 neurons at the first layers, 3 at the second and 2 a the third hidden layer.
Well what you call threshold is the Bias in machine learning nomenclature. This should be left as an input for the user because it is used during training.
Also, I wonder why you are not using the builtin matlab functions. i.e newp or newff. e.g.
ff=newp(X,Y)
Then you can set the properties of the object ff to do your job for selecting gradient descent and so on.