Modelling Projectile Motion using Matlab ode45 - matlab

So I am trying to model simple projectile motion (no air resistance etc) using the ode45 solver in Matlab. This is my code so far:
function [x,y] = trajectory_without_AR_45(v0,theta, dt)
%Path of mortar without air resistance using ode45
g = 9.81;
t_start = 0;
t_end = 100;
%Initial Conditions
y01 = 0; %initial x
y02 = v0 * cos(theta); %finding initial velocity in x direction
y03 = 0; %initial y
y04 = v0 * sin(theta); % finding intial velocity in y direction
y0 = [y01;y02;y03;y04];
%Derivatives
dy1 = y0(2); %vx
dy2 = 0; %ax
dy3 = y0(4); %vy
dy4 = -g; %ay
dy = [dy1;dy2;dy3;dy4];
%Using ODE45
f = # (t, y) (dy);
solution = ode45(f, [t_start, t_end], y0);
t = t_start : 0.01: t_end;
y = deval(solution, t);
plot (y(:,1), y(:,3)); %plotting trajectory
end
However, the plot I am getting is just a straight line which clearly is not correct. Any help would be appreciated.

I think you're not calling the ode solver properly, you only seem to be using the initial conditions to compute dy, which is wrong. Best to put the ode function in a separate function (file). For example, the following is in missile.m:
function dY = missile(t,Y)
g = 9.81;
dY(1) = Y(2); %vx
dY(2) = 0; %ax
dY(3) = Y(4); %vy
dY(4) = -g; %ay
end
Which you would then call as follows:
t_start = 0;
t_end = 2.3; % changed to something more consistent with when y<0
v0 = 10; % made up
theta=pi/4; % made up
y01 = 0; %initial x
y02 = v0 * cos(theta); %finding initial velocity in x direction
y03 = 0; %initial y
y04 = v0 * sin(theta); % finding intial velocity in y direction
y0 = [y01;y02;y03;y04];
opts = odeset('MaxStep',0.01,'InitialStep',0.001);
[t,y] = ode45(#missile, [t_start, t_end], y0, opts);
plot(t,y)
legend('x','dx','y','dy')
which gives the following results:

Related

Plot two-dimensional array as elliptical orbit

I am attempting to plot an elliptical orbit based on a 2-D position array, beginning at p= [5 0]. The plot charts positions from a timeframe t, here between 0 and 100. The calculation uses the formula F = -(p/||p||)(m*M/(p^2) to approximate acceleration and velocity. The result should look like the following:
This is my current code. It plots a completely different shape. Is the problem in my way of interpreting the force equation?
Any other help and comments are much appreciated.
t = 0; p = [50 0]; v = [0 8]; %Initial conditions
dt = 0.05;
M = 10000; m= 1;
tmax = 100;
figure, hold on
d = 0.001
clf;
while t < tmax
F = -(p./norm(p)).*(m*M./(p*p'));
a = F./m - d*v;
v = v + a*dt;
p = p + v*dt;
t = t + dt;
plot(p(1),t,'o','MarkerSize',0.5);
hold on;
plot(p(2),t,'o','MarkerSize',0.5);
end
You want p(1) in the x axis and p(2) in the y axis, with t as a parameter. So you need to replace the two plot lines by plot(p(1),p(2),'o','MarkerSize',0.5); (keeping hold on):
t = 0; p = [50 0]; v = [0 8]; %Initial conditions
dt = 0.05;
M = 10000; m= 1;
tmax = 100;
figure, hold on
d = 0.001
clf;
while t < tmax
F = -(p./norm(p)).*(m*M./(p*p'));
a = F./m - d*v;
v = v + a*dt;
p = p + v*dt;
t = t + dt;
hold on
plot(p(1),p(2),'o','MarkerSize',0.5); %%% modified line
end

How to plot a right triangle path in MATLAB

The following code is used to plot a circular path:
% Head velocity
v = 1.5;
% Angular velocity
w = 1;
% Radius
R = v/w;
% Time
dt = 0.1;
t = 0:dt:(2*pi*R/v);
% Initial mobile robot position vector
x0 = 0; y0 = 0; th0 = 0;
P = [];
P(:,1) = [x0 y0 th0];
% Loop for all time steps
for k = 1 : length(t)
P(:,k+1) = P(:,k) + dt*[v*cos(P(3,k));v*sin(P(3,k));w];
plot(P(1,1:k+1),P(2,1:k+1))
pause(0.01)
axis square
axis([-2 2 -0.5 3.5])
end
, how can I manipulate the position vector to plot a right triangle path.
Thanks in advance.

spectral solution to 1D KdV equation

I am trying to solve the solution of a 1D KdV equation (ut+uux+uxxx=0) starting from a two solitons initial condition using Fourier spectral method. My code blows up the solution for a reason that I cannot figure out. I would appreciate any help. This is my main code file:
%Spatial variable on x direction
L=4; %domain on x
delta=0.05; %spatial step size
xmin=-L; %minimum boundary
xmax=L; %maximum boundary
N=(xmax-xmin)/delta; %number of spatial points
x=linspace(xmin,xmax,N); %spatial vector
% 1D Initial state
sigma1 = 2; sigma2 = 4;
c1 = 2; c2 = 1;
h1 = 1; h2 = 0.3;
U = h1*sech(sigma2*(x+c1)).^2+h2*sech(sigma1*(x-c2)).^2;
%Fast Fourier Transform to the initial condition
Ut = fftshift(fft(U));
Ut = reshape(Ut,N,1);
%1D Wave vector disretisation
k = (2*pi/L)*[0:(N/2-1) (-N/2):-1];
k(1) = 10^(-6);
k = fftshift(k);
k = reshape(k,N,1);
%first derivative (advection)
duhat = 1i *k .*Ut;
du = real(ifft(ifftshift(duhat))); %inverse of FT
%third derivative (diffusion)
ddduhat = -1i * (k.^3) .*Ut;
dddu = real(ifft(ifftshift(ddduhat))); %inverse of FT
% Time variable
dt = 0.1; %time step
tspan = [0 4];
%solve
Time = 50;
for TimeIteration = 1:2:Time
t= TimeIteration * dt;
[Time,Sol] = ode45('FFT_rhs_1D',tspan,U,[],du,dddu);
Sol = Sol(TimeIteration,:);
%plotting
plot(x,abs(Sol),'b','LineWidth',2);
end
And this is the function that solves the equation:
function rhs = FFT_rhs_1D(tspan,U,dummy,du,dddu)
%solve the right hand side
rhs = - U .* du - dddu;
end
Thank you.

Finding x intercept in MATLAB

I am trying to find the x intercept of a parabola of a plot using
x0 = interp1(y,x,0)
However because my parabola starts at the origin it returns 0.
How do I find the x intercept that lies away from the origin? At the moment I am estimating by eye-ball.
Code for the plot:
global k g
g = 10;
v0 = 150;
theta = pi/4;
m = 1;
k = 0.001;
tspan = [0 22];
IC = [0; v0*cos(theta); 0; v0*sin(theta)];
[t, oput] = ode45(#dataODE, tspan, IC);
x = oput(:,1);
vx = oput(:,2);
y = oput(:,3);
vy = oput(:,4);
figure(1); clf;
plot(x,y)
where
function [p] = dataODE( t, x)
global k g
p = zeros(4,1);
p(1) = x(2);
p(2) = -k*sqrt(x(2)^2 + x(4)^2)* x(2);
p(3) = x(4);
p(4) = -g -k*sqrt(x(2)^2 + x(4)^2)* x(4);
You could just restrict x and y to only contain the one intercept:
x0 = interp1(y(a:b),x(a:b),0)
but how do you find a and b? One way would be to just use the points before and after y crosses zero (on the way down):
a = find(diff(y > 0) == -1)
b = a+1

Projectile Motion with Drag Force Matlab

I'm trying to model projectile motion with air resistance.
This is my code:
function [ time , x , y ] = shellflightsimulator(m,D,Ve,Cd,ElAng)
% input parameters are:
% m mass of shell, kg
% D caliber (diameter)
% Ve escape velocity (initial velocity of trajectory)
% Cd drag coefficient
% ElAng angle in RADIANS
A = pi.*(D./2).^2; % m^2, shells cross-sectional area (area of circle)
rho = 1.2 ; % kg/m^3, density of air at ground level
h0 = 6800; % meters, height at which density drops by factor of 2
g = 9.8; % m/s^2, gravity
dt = .1; % time step
% define initial conditions
x0 = 0; % m
y0 = 0; % m
vx0 = Ve.*cos(ElAng); % m/s
vy0 = Ve.*sin(ElAng); % m/s
N = 100; % iterations
% define data array
x = zeros(1,N + 1); % x-position,
x(1) = x0;
y = zeros(1,N + 1); % y-position,
y(1) = y0;
vx = zeros(1,N + 1); % x-velocity,
vx(1) = vx0;
vy = zeros(1,N + 1); % y-velocity,
vy(1) = vy0;
i = 1;
j = 1;
while i < N
ax = -Cd*.5*rho*A*(vx(i)^2 + vy(i)^2)/m*cos(ElAng); % acceleration in x
vx(i+1) = vx(i) + ax*dt; % Find new x velocity
x(i+1) = x(i) + vx(i)*dt + .5*ax*dt^2; % Find new x position
ay = -g - Cd*.5*rho*A*(vx(i)^2 + vy(i)^2)/m*sin(ElAng); % acceleration in y
vy(i+1) = vy(i) + ay*dt; % Find new y velocity
y(i+1) = y(i) + vy(i)*dt + .5*ay*dt^2; % Find new y position
if y(i+1) < 0 % stops when projectile reaches the ground
i = N;
j = j+1;
else
i = i+1;
j = j+1;
end
end
plot(x,y,'r-')
end
This is what I am putting into Matlab:
shellflightsimulator(94,.238,1600,.8,10*pi/180)
This yields a strange plot, rather than a parabola. Also it appears the positions are negative values. NOTE: ElAng is in radians!
What am I doing wrong? Thanks!
You have your vx and vy incorrect... vx= ve*sin(angle in radians) and opposite for vy. U also u do not need a dot in between ur initial velocity and the *... That is only used for element by element multiplication and initial velocity is a constant variable. However the dot multiplier will not change the answer, it just isn't necessary..