How to filter high freq signals? - matlab

So I have a task to do for university to filter High frequency signals in MATLAB. I wrote code for it but it doesn't filter correctly. This is my code:
A1 = 7;
A2 = 10;
A3 = 2;
f1 = 934;
f2 = 232;
f3 = 844;
th1 = 5*pi/4;
th2 = pi/4;
th3 = 5*pi/8;
M = 21;
T = 0.7823;
T1 = 0.0331;
T2 = 0.08;
fd = 6395;
K = 3;
Td = 1/fd; % diskretizavimo periodas
N = fix(T/Td); %modeliuojamo signalo reiksmiu skaicius
t = (0:N-1)*Td;
y = A1*sin(2*pi*f1*t + th1)+A2*sin(2*pi*f2*t + th2);
df = 1/T;
Nf=fd/df;
frib=(f1+f2)/2;
Wn = frib/fd;
b = fir1(M, Wn, 'high');
N2=Nf/2;
fasis = (0:Nf-1)*df;
filt_y = filter(b,1, y);
FILT_Y = abs(fft(filt_y, Nf));
figure(17)
subplot(2,1,1)
plot(t(1:T1*2/Td),filt_y(1:T1*2/Td));box('off'); axis tight;
set(gca, 'fontsize', 12); title('Filtruotas sinusu sumos signalas')
subplot(2,1,2)
stem(fasis(1:N2),FILT_Y(1:N2),'.');box('off'); axis tight;
set(gca, 'fontsize', 12); title('Filtruoto sinusu sumos signalo spektras')
frib is the cut-off frequency
And these are my diagrams:
Can you please tell me what can I do to make only one visible in the second diagram (near 1000 freq)? I don't know what I could do more

If you see the Fourier components of your signal before and after, you can clearly see how the first main frequency gets hugely reduced:
noFILT_Y = abs(fft(y, Nf));
subplot(2,1,2)
stem(fasis(1:N2),FILT_Y(1:N2),'.');box('off'); axis tight;
subplot(2,1,1)
stem(fasis(1:N2),noFILT_Y(1:N2),'.');box('off'); axis tight;
But if you follow #irreducible's suggestion:
Wn = frib/(fd/2);

Related

Model Predictive Control (MPC) for electromechanical system

So I want to create an MPC controller for my seesaw-cart system. All the "grunt work" (getting equations of motion, state-space representation etc.) has been done, so I went into coding into MATLAB.
Here's the following:
clc; clear all; close all;
yalmip('clear')
%% Parameters
a = 0.116553; % height of center mass of the pendulum, [m]
b = 0; % position of the weight B on the vertical rod (not taken into consideration)
c = 0.180047; % height of the center of mass of the cart, [m]
mA = 4.839; % mass of the pendulum, [kg]
mB = 0; % not taken into consideration
mC = 1; % mass of the cart, [kg]
g = 9.81; % gravity factor, [m/s^2]
kappa = 0.1; % coefficient of the viscous damping in the rotational joint
J = 0.68; % moment of inertia of the pendulum, [kgm^2]
Ke = 0.077; % motor constant of the EM force, [Vs^-1]
Kt = 0.077; % proportional moment motor constant, [NmA^-1]
Ra = 2.6; % electrical resistance, [ohm]
p = 1/3.71; % motor gearbox ratio
r = 7.7*10^(-3); % effective radius of the motor shaft, [m]
%% Defining the continuous system
A = [0 1 0 0;
(a*mA*g+b*mB*g)/(J+mB*b^2), -kappa/(J+mB*b^2), -mC*g/(J+mB*b^2), -Ke*Kt/(mC*(J+mB*b^2)*Ra*p^2*r^2);
0 0 0 1;
(a*mA*g+b*mB*g)/(J+mB*b^2)-g, -kappa*c/(J+mB*b^2), -c*mC*g/(J+mB*b^2), -(J+mB*b^2+mC*c^2)*Ke*Kt/(mC*(J+mB*b^2)*Ra*p^2*r^2)];
B = [0;
Kt/(mC*(J+mB*b^2)*Ra*p^2*r^2);
0;
(J+mB*b^2+mC*c^2)*Kt/(mC*(J+mB*b^2)*Ra*p^2*r^2)];
C = eye(4); % check
D = 0;
sysC = ss(A, B, C, D);
%% Defining the discrete system
Ts = 10e-3; % sample time
sysD = c2d(sysC,Ts); % discrete time
Ad = sysD.A;
Bd = sysD.B;
%% Formulation of the MPC problem
[nx, nu] = size(B);
Q = eye(nx);
R = eye(nu);
N = 1000;
% Input constraints, maximum and minimum voltage
umin = -6;
umax = 6;
% Still have to find this
xmin = [-deg2rad(10); -deg2rad(50); -0.5; -10];
xmax = [deg2rad(10); deg2rad(50); 0.5; 10];
uVar = sdpvar(repmat(nu,1,N),ones(1,N));
xVar = sdpvar(repmat(nx,1,N+1),ones(1,N+1));
constraints = [];
objective = 0;
ops = sdpsettings('verbose',0,'solver','quadprog');
for k = 1:N
objective = objective + xVar{k}'*Q*xVar{k} + uVar{k}*R*uVar{k};
constraints = [constraints, xVar{k+1} == Ad*xVar{k} + Bd*uVar{k}];
constraints = [constraints , umin <= uVar{k} <= umax , xmin <= xVar{k+1} <= xmax];
end
controller = optimizer(constraints, objective,ops,xVar{1},[uVar{:}]);
%% Simulation of the linearized model
nSim = 1000;
x0 = [0; 0; 0; 0.05]; % initial values, check
time = 0:Ts:nSim*Ts;
x = zeros(nx,nSim+1);
u = zeros(nu,nSim);
x(:,1) = x0;
for i = 2:nSim+1
disp(strcat(['Sim iter: ', num2str(i-1)]));
uOpt = controller{x(:,i-1)};
u(:,i-1) = uOpt(:,1);
x(:,i) = Ad*x(:,i-1) + Bd*u(:,i-1);
end
%% Plot
figure;
subplot(4,1,1);
plot(time,x(1,:), 'LineWidth', 2, 'Color', 'red'); grid; ylabel('{\theta} (rad)'); title('States');
subplot(4,1,2);
plot(time,x(2,:), 'LineWidth', 2, 'Color', [0.6350, 0.0780, 0.1840]); grid; ylabel('$\dot{\theta}$ (rad/s)', 'Interpreter', 'latex');
subplot(4,1,3);
plot(time,x(3,:), 'LineWidth', 2, 'Color', [0.4940, 0.1840, 0.5560]); grid; ylabel('s (m)');
subplot(4,1,4);
plot(time,x(4,:), 'LineWidth', 2, 'Color',[0, 0.7, 0.9]); grid; ylabel('$\dot{s}$ (m/s)', 'Interpreter', 'latex'); xlabel('t (s)');
figure;
stairs(time(1:end-1),u, 'LineWidth', 2, 'Color',[1, 0.647, 0]); grid; ylabel('Ua (V)'); xlabel('t (s)'); title('Input');
So I was wondering for any suggestions on improvements. What can I do to make my regulator more robust?
Here are my outputs for this particular code:
Note: I'm using YALMIP for the optimization part of the MPC.
You lose feasibility after a few iterations,
sol =
struct with fields:
yalmipversion: '20210331'
matlabversion: '9.9.0.1524771 (R2020b) Update 2'
yalmiptime: 0.1159
solvertime: 0.2331
info: 'Infeasible problem (QUADPROG))'
problem: 1
K>> i
i =
4
Your MPC controller is thus badly tuned (too short horizon being the obvious start)
Also, your definition of u is weird as it has length 4 instead of length N (thus meaning you have two trailing variables in u which never are used, leading to them having value Nan when you look at them)
There are numerous MPC-examples in the tutorials which you should be able to use directly
https://yalmip.github.io/example/standardmpc/
YALMIP-specific question are better asked at
https://github.com/yalmip/YALMIP/discussions
https://groups.google.com/g/yalmip

Bifurcation diagram of discrete SIR model in MATLAB

I have a problem with my MATLAB code to display a figure of a Bifurcation diagram of discrete SIR model.
My model is:
S(n+1) = S(n) - h*(0.01+beta*S(n)*I(n)+d*S(n)-gamma*R(n))
I(n+1) = I(n) + h*beta*S(n)*I(n)-h*(d+r)*I(n)
R(n+1) = R(n) + h*(r*I(n)-gamma*R(n));
I tried out the code below but it keeps MATLAB busy for almost 30 mins and showed up no figure.
MATLAB code:
close all;
clear all;
clc;
%Model parameters
beta = 1/300;
gamma = 1/100;
D = 30; % Simulate for D days
N_t = floor(D*24/0.1); % Corresponding no of hours
d = 0.001;
r = 0.07;
%Time parameters
dt = 0.01;
N = 10000;
%Set-up figure and axes
figure;
ax(1) = subplot(2,1,1);
hold on
xlabel ('h');
ylabel ('S');
ax(2) = subplot(2,1,2);
hold on
xlabel ('h');
ylabel ('I');
%Main loop
for h = 2:0.01:3
S = zeros(N,1);
I = zeros(N,1);
R = zeros(N,1);
S(1) = 8;
I(1) = 5;
R(1) = 0;
for n = 1:N_t
S(n+1) = S(n) - h*(0.01+beta*S(n)*I(n)+d*S(n)-gamma*R(n));
I(n+1) = I(n) + h*beta*S(n)*I(n)-h*(d+r)*I(n);
R(n+1) = R(n) + h*(r*I(n)-gamma*R(n));
end
plot(ax(1),h,S,'color','blue','marker','.');
plot(ax(2),h,I,'color','blue','marker','.');
end
Any suggestions?
It was very slow because you were plotting a single value of h versus a vector S which had 7200 points. I assumed that you only want to plot the last value of S versus h. So replacing S with S(end) in the plot command changes everything. You really didn't need to use hold and it's better call plot once for each axis, so here is how I would do it:
beta = 1/300;
gamma = 1/100;
D = 30; % Simulate for D days
N_t = floor(D*24/0.1); % Corresponding no of hours
d = 0.001;
r = 0.07;
%%Time parameters
dt = 0.01;
N = 10000;
%%Main loop
h = 2:0.01:3;
S_end = zeros(size(h));
I_end = zeros(size(h));
for idx = 1:length(h)
S = zeros(N_t,1);
I = zeros(N_t,1);
R = zeros(N_t,1);
S(1) = 8;
I(1) = 5;
R(1) = 0;
for n=1:(N_t - 1)
S(n+1) = S(n) - h(idx)*(0.01+beta*S(n)*I(n)+d*S(n)-gamma*R(n));
I(n+1) = I(n) + h(idx)*beta*S(n)*I(n) - h(idx)*(d+r)*I(n);
R(n+1) = R(n) + h(idx)*(r*I(n)-gamma*R(n));
end
S_end(idx) = S(end);
I_end(idx) = I(end);
end
figure(1)
subplot(2,1,1);
plot(h,S_end,'color','blue','marker','.');
xlabel ('h');
ylabel ('S');
subplot(2,1,2);
plot(h,I_end,'color','blue','marker','.');xlabel ('h');
xlabel ('h');
ylabel ('I');
This now runs in 0.2 seconds on my computer.

Putting one legend for many axes

I'm using three axes-Objects to scale my data on the x-axis.
My problem is that i do not know how to get a nice legend for the three plots.
I have to do this cause my real data is sampled with different sample rates.
I edited my m-file for the diagram slightly cause normally I'm reading the data out of some txt files.
In this example i used example_data 1 to 3 for my data.
In this example I'm scaling the example_data1 so it looks like the same frequency as example_data2.
I do the 'scaling' ax1.XLim = [0 length(x2)].
That's why this solution doesn't work for me: Plot with multiple axes but only one legend.
It uses set(l3,'Parent',ax2); which somehow ruins my approache to scale my data. The scaling is the only solution to my problem cause i don't know the exact relation between the two sampling rates.
my code:
example_data1 = repmat(1:100,1,10);
example_data2 = 2 * repmat(1:0.5:100.5,1,5);
example_data3 = [1:500 500:-1:1];
whole_length_data1 = length(example_data1);
% 1. step
start_of_data = 1;
end_of_data = 1000;
% data2
y2 = example_data2(start_of_data:end_of_data);
x2 = 0:length(y2)-1;
% data3
y3 = example_data3(start_of_data:end_of_data);
x3 = 0:length(y3)-1;
% data1
y1 = example_data1(1:length(example_data1));
x1 = 0:length(y1)-1;
% 2. step
start_one = 1;
y1 = example_data1(start_one:length(example_data1));
x1 = 0:length(y1)-1;
% 3.step
end_one = whole_length_data1 - 500;
y1 = example_data1(start_one:end_one);
x1 = 0:length(y1)-1;
Farbe1 = [0,1,0]*0.6; % Dunkelgrün
Farbe2 = [1,0,0]*0.8; % Dunkelrot
Farbe3 = get(groot,'DefaultAxesColorOrder') % default values
Farbe3 = Farbe3(1,:); % 1. Zeile der defaultvalues
figure(1)
% 3 axes
clf
%------------------------------------------------------------------
%-------------------------- plot1: ---------------------------
%------------------------------------------------------------------
plot(x2,y2,'green','LineWidth',2,'Color',Farbe1,...
'DisplayName','name of the first plot')
ax1 = gca;
ax1.XLim = [0 length(x2)]
ax1.YLim = [min(y2) max(y2)]
ax1.YTick = [0:25:300]
ax1.FontSize = 12;
legend('show')
%----------------------------------------------------------------
%-------------------------- plot2: --------------------------
%----------------------------------------------------------------
ax2 = axes('Position',ax1.Position);
plot(x3,y3,'blue','LineWidth',2,'Color',Farbe3,...
'DisplayName','plot2')
ax2.Color = 'none';
ax2.XTick = [];
ax2.XLim = [0 length(x3)];
ax2.YAxisLocation = 'right';
ax2.FontSize = 12;
legend('show')
%----------------------------------------------------------------
%-------------------------- plot3: -------------------------
%----------------------------------------------------------------
ax3 = axes('Position',ax1.Position);
plot(x1,y1,'red','LineWidth',2,'Color',Farbe2,...
'DisplayName','3')
ax3.XTick = [];
ax3.YTick = [];
ax3.Color = 'none';
ax3.XAxisLocation = 'top';
ax3.YAxisLocation = 'right';
ax3.XLim = [0 length(x1)];
ax3.YLim = [min(y1) max(y1)*2];
legend('show')
This results in a very bad looking legend:
I really hope somebody can help me.
Thank very much.
You can get better results by storing handles for each of your plot lines, then passing those to a single legend call:
...
h1 = plot(x2,y2,'green','LineWidth',2,'Color',Farbe1,...
'DisplayName','name of the first plot');
...
h2 = plot(x3,y3,'blue','LineWidth',2,'Color',Farbe3,...
'DisplayName','plot2');
...
h3 = plot(x1,y1,'red','LineWidth',2,'Color',Farbe2,...
'DisplayName','3');
...
hl = legend(ax3, [h1 h2 h3]); % Place legend in top-most axes
And here's the result:
Just use the real timestamps as x values:
fig = figure;
plot(x1/length(y1)*end_of_data, y1, 'LineWidth',2, 'Color',Farbe1, 'DisplayName','First plot')
hold on
plot(x2/length(y2)*end_of_data, y2, 'LineWidth',2, 'Color',Farbe2, 'DisplayName','Second plot')
plot(x3/length(y3)*end_of_data, y3, 'LineWidth',2, 'Color',Farbe3, 'DisplayName','Third plot')
legend

Merge line stiles in MATLAB legend

I have two datasets which I want to plot in the same figure, e.g. two cosine and two sine plots which just differ in the amplitude:
x = -pi:pi/20:pi;
hold all;
amplitude = 1;
plot(x,amplitude*cos(x),'-');
plot(x,amplitude*sin(x),'-');
ax = gca;
ax.ColorOrderIndex = 1;
amplitude=3;
plot(x,amplitude*cos(x),'.');
plot(x,amplitude*sin(x),'.');
legend('1*cos(x)','1*sin(x)', '2*cos(x)','2*sin(x)');
hold off;
I want to "compress" the legend so that the two line stiles (normal line and dotted line) are "merged" and appear next to the same textual entry in the legend, such as:
How can I achieve this in MATLAB? I am currently using R2015b.
This is the closest I have got having a quick look with r2015b:
%%
f = figure;
ax = axes;
x = -pi:pi/20:pi;
hold all;
amplitude = 1;
c1 = plot(x,amplitude*cos(x),'-', 'DisplayName', 'cos(x)');
s1 = plot(x,amplitude*sin(x),'-', 'DisplayName', 'sin(x)');
ax.ColorOrderIndex = 1;
amplitude=3;
c2 = plot(x,amplitude*cos(x),'.', 'DisplayName', ' ');
s2 = plot(x,amplitude*sin(x),'.', 'DisplayName', ' ');
lg = legend([c1 c2 s1 s2]);
hold off;
Manipulating legends was easier pre HG2 - so using an older version of Matlab (r2013a) I get:
%%
f = figure;
ax = handle(axes);
x = -pi:pi/20:pi;
hold all;
amplitude = 1;
c1 = plot(x,amplitude*cos(x),'r-', 'DisplayName', 'cos(x)');
s1 = plot(x,amplitude*sin(x),'b-', 'DisplayName', 'sin(x)');
amplitude=3;
c2 = plot(x,amplitude*cos(x),'r.', 'DisplayName', ' ');
s2 = plot(x,amplitude*sin(x),'b.', 'DisplayName', ' ');
lg = handle(legend([c1 c2 s1 s2]));
hold off;
% You need to find which of the children on the legend is
% each of the plots:
c1 = handle(lg.Children(1));
c1.YData = 0.3;
s1 = handle(lg.Children(7));
s1.YData = 0.75;

How can I remove specific regions of a 2D plot in MATLAB?

I have a following MATLAB plot, which consists of a rectangular domain with circular holes on it:
I am modeling a flow through that rectangular porous medium. I have plotted streamlines characterizing that flow. However, the streamlines pass through the entire mesh, which means they also pass through the circular holes on the plot. I would like to remove the streamlines from those holes.
Any suggestions on how to do that?
Here is the code I am using to create that plot:
x = linspace(min(X_plot(:,1)), max(X_plot(:,1)), 100);
y = linspace(min(X_plot(:,2)), max(X_plot(:,2)), 100);
[xg, yg] = meshgrid(x, y);
Fx = TriScatteredInterp(X_plot(:,1), X_plot(:,2), qx);
Fy = TriScatteredInterp(X_plot(:,1), X_plot(:,2), qy);
qxg = Fx(xg,yg);
qyg = Fy(xg,yg);
figure(1); hold on;
hl = streamslice(xg, yg, qxg, qyg);
set(hl, 'color', 'b','Linewidth',0.5);
To plot the circles (and the ellipse) on the graph I used:
hold on
P2 = [2,-1.5];
r2=.6;
tt = linspace(0,pi*2);
xx = P2(1) + r2*cos(tt);
yy = P2(2) + r2*sin(tt);
plot(xx,yy,'--','Color',[.7 .7 0])
hold on
P3 = [3,1.5];
r3=1.3;
tt = linspace(0,pi*2);
xx = P3(1) + r3*cos(tt);
yy = P3(2) + r3*sin(tt);
plot(xx,yy,'--','Color',[1 .7 0])
hold on
P5 = [5,-1.5];
r5=.8;
tt = linspace(0,pi*2);
xx = P5(1) + r5*cos(tt);
yy = P5(2) + r5*sin(tt);
plot(xx,yy,'--','Color',[1 .7 0])
hold on
P6 = [6,1.5];
r6=.6;
tt = linspace(0,pi*2);
xx = P6(1) + r6*cos(tt);
yy = P6(2) + r6*sin(tt);
plot(xx,yy,'--','Color',[1 .7 0])
hold on
P4 = [9,0];
r41=.5;
r42=2.4;
tt = linspace(0,pi*2);
xx = P4(1) + r41*cos(tt);
yy = P4(2) + r42*sin(tt);
plot(xx,yy,'--','Color',[.9 .7 0])