Problem with defining a transfer function for Bode plot in MATLAB - 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

Related

Unable to plot vector field using quiver in 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.

How do I fit experimental data to an ODE (michaelis-menten) equation to get the constants?

I'm trying to get the kf kr and kcat from the ODE equations given by the derivation of the Michaelis-Menten equation. (https://en.wikipedia.org/wiki/Michaelis%E2%80%93Menten_kinetics).
I have experimental data form a simulation and the aproximate values of the k. I need to get a good fit for the k and I don't know how to do it, I try with lsqcurvefit the problem is that I have 2 equations and too many variables and I couldn't find any example of sth similar. If u execute the code u can see both plots the one of the equation and the experimental but I dont know how to put it together.
Thank you in advance
(plot taked from the code)
close all; clear all; clc
%Michaelis Menten Kinetics
%Simple Model for Single Substrate Catalyzed Reactions
% Initial Data
global e0 s0 c0 volum
volum=50^3;
e0=10/volum;
s0=500/volum;
c0=0;
% Load experimental data
data=dlmread("rk_output.txt");
% Assign the data vectors
global timeR subs enz compl prod
timeR=data(:,2); % time
subs=data(:,3)/volum; % Substrate
enz=data(:,4)/volum; % Enzyme
compl=data(:,5)/volum; % Complex
prod=data(:,6)/volum; % Product
% Unknown coefficients
global k
k=[1.66, 7.1E-4, 3.5E-4]; %k1 k2 k-1
% Fitting Curves to Data using Nonlinear Regression
fun=#(t,sc) [k(3)*sc(2)-k(1)*sc(1)*(e0-sc(2)); k(1)*sc(1)*(e0-sc(2))-(k(3)+k(2))*sc(2) ];
time_period=linspace(0,1000,500);
initial=[s0,c0];
[t,sc]=ode45(fun,time_period,initial);
% Assign the data vectors
substrate=sc(:,1);
complex=sc(:,2);
enzyme=(e0-complex);
product=(initial(1)-substrate-complex);
% Plot the raw data
figure(1)
plot(timeR,enz,timeR,compl,t,enzyme,t,complex)
xlabel ('time (ns)')
ylabel ('Particles')
title ('Figure 1')
legend('EnzymeReal','ComplexReal','Enzyme','Complex')

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.

How to do MCMC simulation using Metropolis hasting algorithm in Matlab?

I am trying to simulate a distribution for parameter theta f= theta ^(z_f+n+alpha-1)*(1-theta)^(n+1-z_f-k+ beta-1), where all the parameter except for theta is know. I am using Metro polish hasting algorithm to do the MCMC simulation . My proposal density is a beta distribution with parameter alpha and beta. My code for the simulation are as follows. I am using a buitlin Matlab code called mhsample() for this purpose, How do I know if my code is working properly?
clear
clc
alpha=2;
beta=2;
z_f=1;
n=6;
k=5;
nsamples = 3000;
pdf= #(x) x^(z_f+n+alpha-1)*(1-x)^(n+1-z_f-k+beta-1); % here x acts as theta
proppdf= #(x,y) betapdf(x, alpha, beta);
proprnd =#(x) betarnd(alpha,beta,1);
smpl = mhsample(0.1,nsamples,'pdf',pdf,'proprnd',proprnd,'proppdf',proppdf);
I'm unsure of what you're asking when you say "how do I know if my code is working properly" -- I'm assuming it executes? But for a visual comparison of your function vs. the simulation, you can plot both the PDF and the data you got from mhsample as follows:
% i'm assuming you ran the code above so that smpl and #pdf are both defined...
fplot(pdf,[0 1]); % fplot takes your function and plots it between x-limit [0,1]
figure % new figure
hist(smpl,30); % 30 here is bin size, change it to your preference
Figure below:
the histogram of smpl's output on left, i.e., your simulation
the function pdf bounded in [0,1] on right for comparison to your simulation
This was just a wild guess because those two figures resemble each other and are also beta-distribution-esque.
If you want a more complex analysis than that, I'm afraid I'm not yet proficient in MCMC :)

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