Unable to plot vector field using quiver in Matlab - matlab

I am quite new to Matlab so I apologize if I am making some obvious mistakes, but I have a second order ordinary differential equation that I am trying to plot the vector field of. I have looked at various resources on this site, the MATLAB documentation and MATLAB forums but I am still having trouble.
I have tried solving the ODE with the ode45 function, this gives my a single solution that I can plot. I am using the function odeToVectorField to transform my ODE into a system of first order ODE. I have a feeling this is what is preventing me from properly doing what I want because it give me a set of symbolic equations that I am difficulty to evaluate over the meshgrid.
Here is my code so far:
% Setup outside variables
clear
mu = 0.75; % resistance variable
l = 1; % length of pendulum
g = 9.81; % gravity
% Next we setup the domains of the vector space.
xdom = linspace(-pi,pi,51); % define the X axis space
ydom = linspace(-pi,pi,51); % define the Y axis space
[X,Y] = meshgrid(xdom,ydom); % create a meshgrid for the vector field
% Define the system of ODEs
syms y(t)
eqn = diff(y,t,2) == - mu.*diff(y,t,1) - (g/l).*sin(diff(y,t,0));
U = odeToVectorField(eqn) % this is the part where I think I am doing wrong
Uf = matlabFunction(U(1), 'vars',{'t','Y'}) % trying to set a function handle for the first ODE
Vf = matlabFunction(U(2), 'vars',{'t','Y'}) % trying to set a function handle for the second ODE
% Now we plot it
figure
quiver(X,Y,Uf(X,Y), Vf(X,Y))
Here is a screenshot of my output. I have purposefully left out some semi colons to help you visualize what I am trying to do.
Thank you very much for your help.

Related

Problem with defining a transfer function for Bode plot in MATLAB

I am trying to tune a PID controller using Matlab(not Simulink because I am learning/uni coursework).
1. Summarize the problem:
So, I have a transfer function of a system for which there are phase margin requirement that needs to met
In order to find the phase advance part of the PID I need to solve a bunch of equations to plot a Bode plot using the variables calculated
2.Describe what I've tried
I tried to replace the tf([num],[den]) with real numbers but that is not feasible as it defeats the purpose of doing this, I want Matlab to calculate the GR and frequency and substitute that into the tf
Problem
Full_Code:
https://drive.google.com/file/d/1sWUnvvye_RBXGL8-nWq___3F5UDmDOoG/view?usp=sharing
Minimum reproducible code example:
clearvars;clc;clearAllMemoizedCaches;clear
syms s w
%--------------TF of the aircraft
G(s)= (160*(s+2.5)*(s+0.7))/((s^2+5*s+40)*(s^2+0.03*s+0.06));
k= 8; % selected k value range 4<k<8
Max_PA=asind((k-1)/(k+1)); % computes max phase advance
Centre_dB= 20*log10(sqrt(k)); % computing centre gain in dB
Poi= -120-Max_PA % looking for Point of interest(Poi)
tf_int= subs(G(s),1j*w); %intermediate transfer function
eqn= atan2d(imag(tf_int),real(tf_int))==Poi; % solve for w at Poi
% computing crossover freq(wc)
wc= vpasolve(eqn,w); % find exactly the wc at Poi
GR=20*log10(abs(subs(tf_int,w,wc))); % find the gain at at wc
Kpa= 10^((GR-Centre_dB)/20);
ti= 1/(sqrt(k)*wc); % computing Kpa and ti
num1= [Kpa*k*ti,Kpa];
den2= [ti,1];
PA= tf(num1,den2) %PA tf defined
Yo are trying to input non-numerical (symbolic numers) values into tf, which only accepts numerical arrays. You can convert them to that with double()
PA= tf(double(num1),double(den2)) %PA tf defined

spline interpolation and its (exact) derivatives

Suppose I have the following data and commands:
clc;clear;
t = [0:0.1:1];
t_new = [0:0.01:1];
y = [1,2,1,3,2,2,4,5,6,1,0];
p = interp1(t,y,t_new,'spline');
plot(t,y,'o',t_new,p)
You can see they work quite fine, in the sense interpolating function matches the data points at the nodes fine. But my problem is, I need to compute the exact derivative of y (i.e., p function) w.r.t. time and plot it against the t vector. How can it be done? I shall not use diff commands, because I need to make sure the derivative function has the same length as t vector. Thanks a lot.
Method A: Using the derivative
This method calculates the actual derivative of the polynomial. If you have the curve fitting toolbox you can use:
% calculate the polynominal
pp = interp1(t,y,'spline','pp')
% take the first order derivative of it
pp_der=fnder(pp,1);
% evaluate the derivative at points t (or any other points you wish)
slopes=ppval(pp_der,t);
If you don't have the curve fitting toolbox you can replace the fnderline with:
% piece-wise polynomial
[breaks,coefs,l,k,d] = unmkpp(pp);
% get its derivative
pp_der = mkpp(breaks,repmat(k-1:-1:1,d*l,1).*coefs(:,1:k-1),d);
Source: This mathworks question. Thanks to m7913d for linking it.
Appendix:
Note that
p = interp1(t,y,t_new,'spline');
is a shortcut for
% get the polynomial
pp = interp1(t,y,'spline','pp');
% get the height of the polynomial at query points t_new
p=ppval(pp,t_new);
To get the derivative we obviously need the polynomial and can't just work with the new interpolated points. To avoid interpolating the points twice which can take quite long for a lot of data, you should replace the shortcut with the longer version. So a fully working example that includes your code example would be:
t = [0:0.1:1];
t_new = [0:0.01:1];
y = [1,2,1,3,2,2,4,5,6,1,0];
% fit a polynomial
pp = interp1(t,y,'spline','pp');
% get the height of the polynomial at query points t_new
p=ppval(pp,t_new);
% plot the new interpolated curve
plot(t,y,'o',t_new,p)
% piece-wise polynomial
[breaks,coefs,l,k,d] = unmkpp(pp);
% get its derivative
pp_der = mkpp(breaks,repmat(k-1:-1:1,d*l,1).*coefs(:,1:k-1),d);
% evaluate the derivative at points t (or any other points you wish)
slopes=ppval(pp_der,t);
Method B: Using finite differences
A derivative of a continuous function is at its base just the difference of f(x) to f(x+infinitesimal difference) divided by said infinitesimal difference.
In matlab, eps is the smallest difference possible with a double precision. Therefore after each t_new we add a second point which is eps larger and interpolate y for the new points. Then the difference between each point and it's +eps pair divided by eps gives the derivative.
The problem is that if we work with such small differences the precision of the output derivatives is severely limited, meaning it can only have integer values. Therefore we add values slightly larger than eps to allow for higher precisions.
% how many floating points the derivatives can have
precision = 10;
% add after each t_new a second point with +eps difference
t_eps=[t_new; t_new+eps*precision];
t_eps=t_eps(:).';
% interpolate with those points and get the differences between them
differences = diff(interp1(t,y,t_eps,'spline'));
% delete all differences wich are not between t_new and t_new + eps
differences(2:2:end)=[];
% get the derivatives of each point
slopes = differences./(eps*precision);
You can of course replace t_new with t (or any other time you want to get the differential of) if you want to get the derivatives at the old points.
This method is slightly inferior to method a) in your case, as it is slower and a bit less precise. But maybe it's useful to somebody else who is in a different situation.

Octave equivalent of MATLAB ltitr.m function

I am trying to get some MATLAB scripts to run in Octave, but have a problem with the following line of code:
x = ltitr( a, b, u, x0 ) ;
which throws an error in Octave.
Online research shows that the ltitr function is an internal MATLAB function that returns the Linear time-invariant time response kernel for the given inputs. This sounds as if it should be a common DSP requirement, so I feel that this must be implemented directly in Octave, or in the latest Control package from Source Forge. However, I can't seem to find an Octave equivalent. I've read the documentation for the latest Octave Control package and maybe I should be using the functions lsim.m or ss.m or dss.m or impulse.m but I'm not really sure.
Can anyone enlighten me? If it's not implemented in Octave, maybe some online reference to code that I could use to write my own ltitr function?
If you actually type in help ltitr in the MATLAB command prompt, you come up with this documentation:
%LTITR Linear time-invariant time response kernel.
%
% X = LTITR(A,B,U) calculates the time response of the
% system:
% x[n+1] = Ax[n] + Bu[n]
%
% to input sequence U. The matrix U must have as many columns as
% there are inputs u. Each row of U corresponds to a new time
% point. LTITR returns a matrix X with as many columns as the
% number of states x, and with as many rows as in U.
%
% LTITR(A,B,U,X0) can be used if initial conditions exist.
% Here is what it implements, in high speed:
%
% for i=1:n
% x(:,i) = x0;
% x0 = a * x0 + b * u(i,:).';
% end
% x = x.';
% Copyright 1984-2007 The MathWorks, Inc.
% $Revision: 1.1.6.4 $ $Date: 2007/05/23 18:54:41 $
% built-in function
As such, they pretty much already give you the code for it. However, I'm assuming that this is written in MEX and so that's why it's built-in and is super fast. As such, if you want to port this over to Octave, you just have to use the code they reference above. It won't be as fast as MATLAB's version though, but that for loop is essentially the basic way to implement it.
However, for the sake of completeness, let's write our own Octave function for it:
function x = ltitr(A, B, U, x0)
%// Number of rows in U is the number of time points
num_points = size(U, 1);
%// Number of columns in U is how many inputs we have
num_inputs = size(U, 2);
x = zeros(num_inputs, num_points); %// Pre-allocate output
%// For each time point we have ...
for idx = 1 : num_points
x(:,idx) = x0; %// Output the corresponding time point
x0 = A*x0 + B*U(idx,:).'; %// Compute next time point
end
x = x.';
The above function is almost similar to the code you see in MATLAB, but there are some additional steps I did, such as pre-allocating the matrix for efficiency, as well as getting some relevant variables to help with the computation. Also, take note that the output matrix x is defined with the dimensions flipped. The reason why is because the computation of the output at each point in time is more easier to compute in this state. If you don't, then you'll have to do unnecessary transposing for the other variables defined in the x0 = ... statement. As such, it's easier to do the calculations in the transposed matrix. When you're done, you transpose the resulting matrix to give you the final output matrix x.
The default state for x0 I'm assuming is going to be all zeroes, so if you want to use this as the default state, specify x0 = zeros(n,1); where n is the total number of inputs for your LTI system.

Quantile regression with linprog in Matlab

I am trying to implement the quantile regression process with a simple setup in Matlab. This page contains a description of the quantile regression as a linear program, and displays the appropriate matrices and vectors. I've tried to implement it in Matlab, but I do not get the correct last element of the bhat vector. It should be around 1 but I get a very low value (<1e-10). Using another algorithm I have, I get a value of 1.0675. Where did I go wrong? I'm guessing A, b or f are wrong.
I have tried playing with optimset, but I don't think that is the problem. I think I've made a conversion mistake when going from math to code, I just can't see where.
% set seed
rng(1);
% set parameters
n=30;
tau=0.5;
% create regressor and regressand
x=rand(n,1);
y=x+rand(n,1)/10;
% number of regressors (1)
m=size(x,2);
% vektors and matrices for linprog
f=[tau*ones(n,1);(1-tau)*ones(n,1);zeros(m,1)];
A=[eye(n),-eye(n),x;
-eye(n),eye(n),-x;
-eye(n),zeros(n),zeros(n,m);
zeros(n),-eye(n),zeros(n,m)];
b=[y;
y
zeros(n,1);
zeros(n,1)];
% get solution bhat=[u,v,beta] and exitflag (1=succes)
[bhat,~,exflag]=linprog(f',A,b);
I solved my problem by using the formulation (in the pdf) above the one I tried to implement in the question. I've put it in a Matlab-function if you're interested in the code.
function [ bhat ] = qregressMatlab( y, x, tau )
% bhat are the estimates
% y is a vector of outcomes
% x is a matrix with columns of explanatory variables
% tau is a scalar for choosing the conditional quantile to be estimated
n=size(x,1);
m=size(x,2);
% vectors and matrices for linprog
f=[tau*ones(n,1);(1-tau)*ones(n,1);zeros(m,1)];
Aeq=[eye(n),-eye(n),x];
beq=y;
lb=[zeros(n,1);zeros(n,1);-inf*ones(m,1)];
ub=inf*ones(m+2*n,1);
% Solve the linear programme
[bhat,~,~]=linprog(f,[],[],Aeq,beq,lb,ub);
% Pick out betas from (u,v,beta)-vector.
bhat=bhat(end-m+1:end);
end

MATLAB going from Cart to Pol back to Cart coords for cylindrical plot

1. What I WANT to do:
(i) Use input n to generate an n*n cartesian grid
[x y] = meshgrid(linspace(-1,1,n));
(ii) Generate polar coordinates
[theta r] = cart2pol(x,y);
(iii) Evaluate a function in cylindrical coordinates
z = f(theta,r);
(iv) Plot the result using (say) pcolor (or surf, or anything)
pcolor(x,y,abs(z).^2) %The function is complex, a Laguerre-Gauss to be exact.
2. What I CAN do... The only way I can get the plots to work is by starting with my polar parameters and working back to cartesian from there:
(i) Define parameters
r=linspace(0,1,n); theta=linspace(0,2*pi,n);
(ii) Create both grids and evaluate f
[theta r]=meshgrid(theta,r);
[x y]=pol2cart(theta,r);
z=f(theta,r);
(iii) Plot
pcolor(x,y,abs(z).^2)
The PROBLEM is that now my grid is circular, and I would like to evaluate the function everywhere ON A RECTANGULAR grid (because my analysis depends on having square pixel arrays). The reiterate, using method 2 above, I get a circular plot circumscribed in a square; imagine a black circle with white along the edges... but I WANT to evaluate the function in this "white" region. HOWEVER, using method 1 does NOT work -- the function is all messed up when I plot (Just google Laguerre-Gauss modes to see what the plots should look like).
I want to be able to start with a rect grid and assign every point a polar coordinate, instead of start with polar coordinates and assign them all cartesian points.
I've been messing with this on an off for a long time, and I can't figure out how to get around this seemingly simple issue.
Edit 1
It seems that the problem lies in how the coordinate matrices are generated. Below I've posted screen-shots of a simple 3by3 example illustrating how approach 1 and approach 2 generate different numbers.
How to make these numbers compatible?
I have no reputation points so I cannot upload the images directly... links below show the 3by3 example... see comments for links to actual images of the Laguerre-Gauss plots I'm trying to make...
apply cart2pol
apply pol2cart
Edit 2
Currently, the result of approach (1.) gives wrong results, as shown here:
desired approach, wrong result
The second approach gives the right images, unfortunately it's only a circle and not the entire square. It is shown here:
implemented approach, limited result
3D plots of both approaches are shown here - only the colorful part of the top figure is correct.
Edit 3
Here is a screenshot of the function f which is being used above. Note, that it asks for more input parameters than just r,theta. Typical values are:
w0 = 0.5;
p = 0;
l = 5;
The function C gives a normalization and L are Laguerre polynomials. Both of these functions have been thoroughly tested and yield the expected results.
Edit 4
Here is enough code to run my example z=U(0,5,r,phi,w0)+U(0,-5,r,phi,w0); explicitly. The plot itself is given by pcolor(x,y,abs(z).^2).
Note that the Lpl() function is inserted as a comment. This will have to be saved as its own m-file for the U function to run properly.
%% Laguerre-Gauss Modes U = U(p,l,r,phi,w0)
% Source: OAM theory paper section 2.A eqn 1.
% Assuming POLAR coordinates and evaluating AT beam waist.
% -- That is, z=0 for w(z)=w0(sqrt(1+z/zR))
% ---- ie, w(0) = w0
% Assuming z=0 also renders the Gouy phase arctan(z/zR) irrelevant.
% Note: Rayleigh Range zR is not explicitly defined because z=0 --> it is irrelevant too.
% Since zR is the only wavelength dependent term, wavelength also doesn't
% matter.
function out = U(p,l,r,phi,w0)
%Function handles for clarity
e = #(x) exp(x);
C = #(p,l) sqrt((2*factorial(p))/(pi*factorial(p+abs(l))));
L = #(p,l,z) Lpl(p,l,z);
%% Lpl() FUNCTION
% function out = Lpl(p,l,z)
%
% l=abs(l);
% LL=0;
% for mm=1:p+1
% m=mm-1;
% L=LL;
% LL= L+((-1)^m)*(factorial(p+l)/(factorial(p-m)*factorial(l+m)*factorial(m)))*(z.^m);
% end
% out = LL;
%%
out = (C(p,l)/w0)*...
(((sqrt(2).*r)/w0)^abs(l))*...
(e((-r.^2)/w0^2))*...
(L(p,l,((2.*r.^2)/w0^2)))*...
(e((-1)*1i*l.*phi)); ``
Edit
The answer was rewritten based on the code provided in Edit 4 of the question.
I think the trouble stems from the function U. You don't apply element wise operations to all parts of the equation. If you change it to:
out = (C(p,l)./w0).* ... % here it's a .* instead of *
(((sqrt(2).*r)./w0).^abs(l)).* ... % here it's a .* instead of *
(e((-r.^2)./w0.^2)).* ... % here it's a .* instead of *
(L(p,l,((2.*r.^2)./w0.^2))).* ... % here it's a .* instead of *
(e((-1)*1i*l.*phi));
You get the following two results, shown below.
This figure used an input of cartesian coordinates:
And this figure used the polar coordinates:
The "coarser" resolution in the second figure is due to the less suitable resolution of the grid. But in essence you resolve the same features.