I need help creating a closed-loop system using unity feedback such that the system resembles the one in the image.
There are 4 states in the system and K is a 1x4 matrix. The open loop system is described by:
%State-space model
A=[-0.231308504369119,0.0544096693079551,-0.000124548233093912,-0.990288665751696;0,0,1,0;-21.9913440608126,0,-4.27507057923922,1.16034911016267;11.8852437044909,0,-0.450303860814642,-0.711734908447950];
B=[-0.0109680172306510,0.0630660990762435;0,0;-32.2767539463422,5.44547987525456;-2.63365317966200,-7.15884612728451];
C=eye(4);
D=zeros(4,1);
% this is the cruise speed (TAS)
V = 180;
g0 = 9.81;
%% Open-loop response
% Check the eigenvalues. Note the bad damping of the Dutch roll and
% spiral modes
eigA = eig(A);
% Aileron control only.
Ba = B(:,1);
% Create state-space system (open loop system, only aileron control), generate simulation output for a step input on
% the aileron
sa = ss(A, Ba, C, D);
I have tried:
feedback(K,-1*ones(1,4),-1)
but this doesn't work. I get the error:
not enough input arguments
How do I fix this?
Related
I am trying to study some codes inside a wireless communication textbook, which I have a piece of code from the textbook:
function PL=PL_free(fc,dist,Gt,Gr)
% Free Space Path loss Model
% Input
% fc : carrier frequency[Hz]
% dist : between base station and mobile station[m]
% Gt : transmitter gain
% Gr : receiver gain
% output
% PL : path loss[dB]
lamda = 3e8/fc;
tmp = lamda./(4*pi*dist);
if nargin>2
tmp = tmp*sqrt(Gt);
end
if nargin>3
tmp = tmp*sqrt(Gr);
end
PL = -20*log10(tmp);
And inside the textbook, there is also a graph that is generated based on this Matlab code. My question is, how can I create this graph based on the function myself? Do I need to have a data source for all of the variables? If I cannot get a data source like an excel file, is there any way inside Matlab there is a built-in tool that supports creating this graph? The graph is like this:
(I understand the concept of the plot which is in the command, enter some data of the function, but it will only show the answer of the function output. I cannot find a suitable solution anywhere online so here I come)
After revision:
I haven't testet this, but something along the lines of:
fc = __ % Choose value
Gt = __ % Choose value
Gr = __ % Choose value
dist = logspace(0, 3, 16);
PL=PL_free(fc,dist,Gt,Gr);
semilogx(dist, PL, 'ro')
Alternatively:
dist = logspace(0, 3, 16);
PL = zeros(1, numel(dist));
for ii = 1:numel(dist)
PL(ii) = PL_free(fc, dist, Gt, Gr);
end
semilogx(dist, PL, 'ro')
I'm not sure if linspace or logspace is best here.linspace creates a vector with equally spaced values, while logspace creates a vector with logarithmically spaced values. To plot more values you can do hold on or hold all, and do semilogx with a new PL.
I want to determine how well the estimated model fits to the future new data. To do this, prediction error plot is often used. Basically, I want to compare the measured output and the model output. I am using the Least Mean Square algorithm as the equalization technique. Can somebody please help what is the proper way to plot the comparison between the model and the measured data? If the estimates are close to true, then the curves should be very close to each other. Below is the code. u is the input to the equalizer, x is the noisy received signal, y is the output of the equalizer, w is the equalizer weights. Should the graph be plotted using x and y*w? But x is noisy. I am confused since the measured output x is noisy and the model output y*w is noise-free.
%% Channel and noise level
h = [0.9 0.3 -0.1]; % Channel
SNRr = 10; % Noise Level
%% Input/Output data
N = 1000; % Number of samples
Bits = 2; % Number of bits for modulation (2-bit for Binary modulation)
data = randi([0 1],1,N); % Random signal
d = real(pskmod(data,Bits)); % BPSK Modulated signal (desired/output)
r = filter(h,1,d); % Signal after passing through channel
x = awgn(r, SNRr); % Noisy Signal after channel (given/input)
%% LMS parameters
epoch = 10; % Number of epochs (training repetation)
eta = 1e-3; % Learning rate / step size
order=10; % Order of the equalizer
U = zeros(1,order); % Input frame
W = zeros(1,order); % Initial Weigths
%% Algorithm
for k = 1 : epoch
for n = 1 : N
U(1,2:end) = U(1,1:end-1); % Sliding window
U(1,1) = x(n); % Present Input
y = (W)*U'; % Calculating output of LMS
e = d(n) - y; % Instantaneous error
W = W + eta * e * U ; % Weight update rule of LMS
J(k,n) = e * e'; % Instantaneous square error
end
end
Lets start step by step:
First of all when using some fitting method it is a good practice to use RMS error . To get this we have to find error between input and output. As I understood x is an input for our model and y is an output. Furthermore you already calculated error between them. But you used it in loop without saving. Lets modify your code:
%% Algorithm
for k = 1 : epoch
for n = 1 : N
U(1,2:end) = U(1,1:end-1); % Sliding window
U(1,1) = x(n); % Present Input
y(n) = (W)*U'; % Calculating output of LMS
e(n) = x(n) - y(n); % Instantaneous error
W = W + eta * e(n) * U ; % Weight update rule of LMS
J(k,n) = e(n) * (e(n))'; % Instantaneous square error
end
end
Now e consists of errors at the last epoch. So we can use something like this:
rms(e)
Also I'd like to compare results using mean error and standard deviation:
mean(e)
std(e)
And some visualization:
histogram(e)
Second moment: we can't use compare function just for vectors! You can use it for dynamic system models. For it you have to made some workaround about using this method as dynamic model. But we can use some functions as goodnessOfFit for example. If you want something like error at each step that consider all previous points of data then make some math workaround - calculate it at each point using [1:currentNumber].
About using LMS method. There are built-in function calculating LMS. Lets try to use it for your data sets:
alg = lms(0.001);
eqobj = lineareq(10,alg);
y1 = equalize(eqobj,x);
And lets see at the result:
plot(x)
hold on
plot(y1)
There are a lot of examples of such implementation of this function: look here for example.
I hope this was helpful for you!
Comparison of the model output vs observed data is known as residual.
The difference between the observed value of the dependent variable
(y) and the predicted value (ŷ) is called the residual (e). Each data
point has one residual.
Residual = Observed value - Predicted value
e = y - ŷ
Both the sum and the mean of the residuals are equal to zero. That is,
Σ e = 0 and e = 0.
A residual plot is a graph that shows the residuals on the vertical
axis and the independent variable on the horizontal axis. If the
points in a residual plot are randomly dispersed around the horizontal
axis, a linear regression model is appropriate for the data;
otherwise, a non-linear model is more appropriate.
Here is an example of residual plots from a model of mine. On the vertical axis is the difference between the output of the model and the measured value. On the horizontal axis is one of the independent variables used in the model.
We can see that most of the residuals are within 0.2 units which happens to be my tolerance for this model. I can therefore make a conclusion as to the worth of the model.
See here for a similar question.
Regarding you question about the lack of noise in your models output. We are creating a linear model. There's the clue.
I'm building a model (test1) in Matlab for Hydraulic Valve.
When i try the optimization tool i get the following error: Error running optimization. Undefined function 'yout' for input arguments of type 'double'.
This is the code for the objective function i use:
function F = obj_find_valve_param_a_max(x,Q_r)
% Objective function to find the maximum valve area parameter value
% Copyright 2010 MathWorks, Inc.
assignin('base','a_max', x);
% If necessary, reset parameterizaton to second option (table)
model = 'test1';
load_system(model);
blkpth = find_system(bdroot,'ClassName','valve_dir_4_way');
set_param(char(blkpth),'mdl_type','1');
sim(model);
k = [1 1 1 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2]; % Weight multipliers
% Computing objective function
F = 0;
for j = 1:11
F = F + k(j) * (yout(j) - Q_r(j))^2;
end
end
% EOF
% Script to find directional valve parameter a_max
% Copyright 2010 MathWorks, Inc.
% This script file invokes optimization process to find the orifice
% area at maximum opening for 4-way directional valve when the valve is
% modeled using the first parameterization option (linear relationship
% between control signal and orifice area).
% init_opening - vaalve initial openings [mm]
% A_leak - leakage area [m^2]
% Q_r - vector of required flow rate at 11 valve displacements
% x0 - initial value for the only variable parameter: orifice maximum area
init_opening = -1; % mm
A_leak = 1e-9; % m^2
% Vector of required flow rates. Read out from plot on page 8 in
% Eaton/Vickers Porportional Directional Valves catalog for KBFDG5V-10 valve
% Actual flow rates are determined at fixed instances of time by exporting
% flow rate measured at the external loop of the valve to the MATLAB
% workspace
Q_r = [0 0 52 150 248 346 450 540 625 670 700];
% Set initial value of the orifice maximum area
x0 = 4.8; % [cm^2]
% Optimization
[x,fval,exitflag,output] = ...
fminsearch(#obj_find_valve_param_a_max,x0, ...
optimset('Tolx',1e-6,'Display','iter'),Q_r);
%bdclose all
If i remove from the first code yout(j) - Q_r(j) the iteration finishes successfully.
Please does anyone knows how to deal with this error?
Thanks.
This error means that MATLAB does not know what to do with the reference to yout. If yout is a variable (I'm guessing that's your intention) then it must be initialised before it can be indexed. The line
yout(j) - Q_r(j)
is an attempt to index the jth element of array yout. Therefor yout must be an array of length at least j. However your code has not initialised the variable, hence the error.
You don't show us your model test1 and more importantly, how it is configured. You need to have a root-level outport block in your model, and have the model configured to have the output saved to a workspace variable yout (see Data Import/Export Pane for details on how to do this). Also, your script (which I suspect is copied from some MathWorks material...) assumes that yout is of length 11. Make sure to set the sample time and/or decimation/output options correctly to make sure that's the case.
I am trying to solve a forced mass-spring-damper system in matlab by using the Runge-Kutta method.
Currently the code uses constant values for system input but instead I would like to vectors as input. For examples, I would like to replace my force amplitude F0 with a vector value.
Should I be using for loops or what is the simplest way to do it?
function O = MSDSRK(m,b,k,F0,w,x0,v0)
% ----- Input argument -----
% m: mass for particle
% b: damping coefficient
% k: spring constant
% F0: amplitude of external force
% w: angular freuency of external force
% x0: initial condition for the position x(0)
% v0: initial condition for the velocity v(0)
dt=0.1;
options=odeset('InitialStep',dt,'MaxStep',dt);
td=[0:dt:50];
% Solve differential equation with Runge-Kutta solver
[t,x]=ode45(#(t,X)MSD(t,X,m,b,k,F0,w),td,[x0;v0],options);
% Extract only particle position trajectory
O=[t x(:,1)];
end
function dX=MSD(t,X,m,b,k,F0,w)
% With two 1st order diffeential equations,
% obtain the derivative of each variables
% (position and velocity of the particle)
dX(1,1)=X(2,1);
dX(2,1)=(1/m)*(F0*sin(w*t)-b*X(2,1)-k*X(1,1));
end
A for-loop will work for sure, but it's not what I'd advise in this situation. That approach has the drawback of making you think in a certain way, namely, that you are solving a simple 1D system, just multiple times.
The for-loop approach doesn't teach you very much more than what you already knew how to do. You'll get a passing grade I'm sure. But if you want to excell, not only here but also in future classes (and more importantly, in your job later), you have to do more. You can only learn how to tackle more complicated problems by thinking about this simple problem in a different way, namely, as a multi-dimensional mass/spring/damper system, of which the components all happen to be uncoupled and all happen to have the same initial values.
For such systems, vectorization and matrix manipulation is really the way to go. That is the generalization of 1D/2D/3D systems, to arbitrary-D systems. And matrix manipulation and vecorization, that is just what MATLAB is best at. That is indeed what you can learn here.
Here's how to do it for your case. I made it a bit smaller in scope, but the principles remain the same:
function O = MSDSRK
% Assign some random scalar values to all parameters, but
% a *vector* to the force amplitudes
[m,b,k,F0,w,x0,v0] = deal(...
1,0.2,3, rand(13,1), 2,0,0);
% We need to simulate as many mass-spring-damper systems as there are
% force amplites, so replicate the initial values
x0 = repmat(x0, numel(F0),1);
v0 = repmat(v0, numel(F0),1);
% The rest is the same as before
dt = 0.1;
options = odeset('InitialStep', dt,'MaxStep', dt);
td = 0:dt:50;
[t,x] = ode45(#(t,X) MSD(t,X,m,b,k,F0,w), td, [x0;v0], options);
% The output is now:
%
% x(:,1) position of mass in system with forcing term F0(1)
% x(:,2) position of mass in system with forcing term F0(2)
% ...
% x(:,14) speed of mass in system with forcing term F0(1)
% x(:,15) speed of mass in system with forcing term F0(2)
% ...
O = [t x(:,1:numel(F0))];
% And, to make the differences more clear:
plot(t, x(:,1:numel(F0)))
end
function dX = MSD(t,X,m,b,k,F0,w)
% Split input up in position and velocity components
x = X(1:numel(X)/2);
v = X(numel(X)/2+1:end);
% Compute derivative
dX = [
v
(F0*sin(w*t) - b*v - k*x)/m
];
end
So I have had a few posts the last few days about using MatLab to perform a convolution (see here). But I am having issues and just want to try and use the convolution property of Fourier Transforms. I have the code below:
width = 83.66;
x = linspace(-400,400,1000);
a2 = 1.205e+004 ;
al = 1.778e+005 ;
b1 = 94.88 ;
c1 = 224.3 ;
d = 4.077 ;
measured = al*exp(-((abs((x-b1)./c1).^d)))+a2;
%slit
rect = #(x) 0.5*(sign(x+0.5) - sign(x-0.5));
rt = rect(x/width);
subplot(5,1,1);plot(x,measured);title('imported data-super gaussian')
subplot(5,1,2);plot(x,(real(fftshift(fft(rt)))));title('transformed slit')
subplot(5,1,3);plot(x,rt);title('slit')
u = (fftshift(fft(measured)));
l = u./(real(fftshift(fft(rt))));
response = (fftshift(ifft(l)));
subplot(5,1,4);plot(x,real(response));title('response')
%Data Check
check = conv(rt,response,'full');
z = linspace(min(x),max(x),length(check));
subplot(5,1,5);plot(z,real(check));title('check')
My goal is to take my case, which is $measured = rt \ast signal$ and find signal. Once I find my signal, I convolve it with the rectangle and should get back measured, but I do not get that.
I have very little matlab experience, and pretty much 0 signal processing experience (working with DFTs). So any advice on how to do this would be greatly appreciated!
After considering the problem statement and woodchips' advice, I think we can get closer to a solution.
Input: u(t)
Output: y(t)
If we assume the system is causal and linear we would need to shift the rect function to occur before the response, like so:
rt = rect(((x+270+(83.66/2))/83.66));
figure; plot( x, measured, x, max(measured)*rt )
Next, consider the response to the input. It looks to me to be first order. If we assume as such, we will have a system transfer function in the frequency domain of the form:
H(s) = (b1*s + b0)/(s + a0)
You had been trying to use convolution to and FFT's to find the impulse response, "transfer function" in the time domain. However, the FFT of the rect, being a sinc has a zero crossing periodically. These zero points make using the FFT to identify the system extremely difficult. Due to:
Y(s)/U(s) = H(s)
So we have U(s) = A*sinc(a*s), with zeros, which makes the division go to infinity, which doesn't make sense for a real system.
Instead, let's attempt to fit coefficients to the frequency domain linear transfer function that we postulate is of order 1 since there are no overshoots, etc, 1st order is a reasonable place to start.
EDIT
I realized my first answer here had a unstable system description, sorry! The solution to the ODE is very stiff due to the rect function, so we need to crank down the maximum time step and use a stiff solver. However, this is still a tough problem to solve this way, a more analytical approach may be more tractable.
We use fminsearch to find the continuous time transfer function coefficients like:
function x = findTf(c0,u,y,t)
% minimize the error for the estimated
% parameters of the transfer function
% use a scaled version without an offset for the response, the
% scalars can be added back later without breaking the solution.
yo = (y - min(y))/max(y);
x = fminsearch(#(c) simSystem(c,u,y,t),c0);
end
% calculate the derivatives of the transfer function
% inputs and outputs using the estimated coefficient
% vector c
function out = simSystem(c,u,y,t)
% estimate the derivative of the input
du = diff([0; u])./diff([0; t]);
% estimate the second derivative of the input
d2u = diff([0; du])./diff([0; t]);
% find the output of the system, corresponds to measured
opt = odeset('MaxStep',mean(diff(t))/100);
[~,yp] = ode15s(#(tt,yy) odeFun(tt,yy,c,du,d2u,t),t,[y(1) u(1) 0],opt);
% find the error between the actual measured output and the output
% from the system with the estimated coefficients
out = sum((yp(:,1) - y).^2);
end
function dy = odeFun(t,y,c,du,d2u,tx)
dy = [c(1)*y(3)+c(2)*y(2)-c(3)*y(1);
interp1(tx,du,t);
interp1(tx,d2u,t)];
end
Something like that anyway should get you going.
x = findTf([1 1 1]',rt',measured',x');