Water Rocket Simulation in MATLAB
The Water Rocket Simulation script was developed in MATLAB using iterative equations, automatically scaling timestep-dependent arrays. It models the entire rocket path, subdivided into the thrust phase, deceleration phase, and parachute phase, allowing for a comprehensive simulation of the rocket’s flight.
Key Contributions
- Created algorithms for thrust, deceleration, and parachute deployment phases.
- Utilised numerical methods for precise iterative integration.
- Displayed plots to visualise parameters comprehensively.
- Translated physical equations into code for accurate simulation.
Responsibilities
- Managed all aspects of the simulation script, ensuring stability and correct usage of physical principles.
- Compared simulation results to own estimates to validate the model.
Key Skills Developed
- Algorithmic Design: Developed custom physics-based algorithms for thrust, deceleration, and parachute phases.
- Numerical Methods: Applied the trapezoidal rule for precise integration of velocity and height calculations.
- Plotting and Analysis: Developed several adaptive plots to visualise array-based parameters.
Simulation Graphs
Code Explanation
Initialisation
- Defined fixed constants and matrices for time-dependent variables.
- Created arrays to save specific variables at each timestamp.
- The array size is determined by the total number of timestamps, scaled from time and timestep (dt).
- Set non-fixed initial parameters for rocket and environmental conditions.
Thrust Phase
- Water exit velocity is calculated using a pseudo-Torricelli equation adapted from Bernoulli’s equation.
- Current mass is adjusted dynamically by subtracting the sum of all massLost.
- The force of thrust is calculated using mass flow rate and water velocity via the thrust equation.
- Total acceleration is computed considering drag forces and gravity.
- Velocity and height are derived from integrating acceleration.
- Break condition when water (fuel) depletes.
Deceleration Phase
- Continues from the last iteration using
last_i
. - Without thrust, most equation components are removed.
- Break condition when velocity becomes negative, indicating the start of freefall.
Parachute Phase
- Drag formula is modified to fit parachute specifications.
- Break condition when the rocket reaches the ground (height < 0).
Plotting
- Results are visualised in automatically scaled graphs, plotting maximum and minimum values to aid in analysis.
Code
% Constants
g = 9.81; % Acceleration due to gravity (m/s^2)
rho = 1.18; % Density of air (kg/m^3)
CD_Bottle = 0.75; % Coefficient of drag of rocket
CD_Parachute = 1.75; % Coefficient of drag of parachute
areaParachute = 0.282; % Area of parachute (m^2)
diaNozzle = 0.0089; % Diameter of nozzle (m)
areaNozzle = pi * (diaNozzle / 2)^2; % Area of nozzle (m^2)
diaBottle = 0.0955; % Diameter of bottle (m)
areaBottle = pi * (diaBottle / 2)^2; % Cross-sectional area of bottle (m^2)
mWingsConnector = 0.0053; % Mass of wings/connector (kg)
mRocketTop = 0.247; % Mass of rocket top (kg)
mBottle = 0.043; % Mass of bottle (kg)
mBattery = 0.005; % Mass of battery (kg)
mPayload = 0.1; % Mass of payload (kg)
dWater = 997; % Density of water (kg/m^3)
% Creating Matrices
dt = 0.0001; % Time step (s)
t = 0:dt:15; % Time array (s) Full flight ~20s Thrust phase ~0.5s
v = zeros(size(t)); % Velocity array (m/s)
h = zeros(size(t)); % Height array (m)
a = zeros(size(t)); % Acceleration array (m/s^2)
p = zeros(size(t)); % Pressure array (Pa)
massLost = zeros(size(t)); % Mass lost array (kg)
mflowrate = zeros(size(t)); % Mass flow rate array (kg/s)
thrust = zeros(size(t)); % Mass flow rate array (kg/s)
velocityWaterout = zeros(size(t));
massCurrent = zeros(size(t));
% Initial conditions
vAir = 0.0013; % Initial volume of air (m^3)
vWater = 0.0007; % Initial volume of water (m^3)
mWater = vWater * dWater; % Mass of water (kg)
mTotal = mWingsConnector + mRocketTop + mBottle + mBattery + mPayload + mWater; % Total initial mass (kg)
p(1) = 6e5; % Initial pressure (Pa)
atmP = 1e5; % Atmospheric pressure (Pa)
constant = vAir * p(1); % PV = constant
v(1)=0;
%0.002 kg
last_i = 0; % keep track of last i from previous loop
% Thrust Phase
for i = last_i+1:length(t)-1
if a(i) >= 0
velocityWaterout(i) = sqrt(2 * (p(i) - atmP) / dWater); % Velocity of water at nozzle
mflowrate(i) = areaNozzle * velocityWaterout(i) * dWater; % Mass flow rate of water out
massLost(i) = mflowrate(i) * dt; % Mass flow
massCurrent(i) = mTotal - sum(massLost); % Adjusting rocket mass due to water ejection
thrust(i) = mflowrate(i) * velocityWaterout(i); % Thrust
a(i+1) = ((thrust(i) - 0.5 * rho * CD_Bottle * areaBottle * v(i)^2) / massCurrent(i) - g); % a = F / m
if p(i) > 390000
p(i+1) = constant / (vAir + sum(massLost) / dWater); %PV = constant
else % Break condition when water finishes
p(last_i+1:length(t)) = atmP; % Assuming pressure equalises instantly and air is light and has negligible work
massCurrent(i:length(t)) = massCurrent(i); % Will remain constant, updates all remaining values to this value
break;
end
v(i+1) = v(i) + (a(i+1) + a(i)) / 2 * dt; % Using trapezoidal rule
h(i+1) = h(i) + (v(i+1) + v(i)) / 2 * dt; % Using trapezoidal rule
last_i = i; % Latest loop iteration
end
end
% Deceleration Phase
for i = last_i+1:length(t)-1 % Resumes where previous loop finished
if v(i) < 0
break; % Stops loop when velocity is negative
end
%a(i) = -g;
a(i) = -g - (0.5 * rho * CD_Bottle * areaBottle * v(i)^2 / mTotal);
v(i+1) = v(i) + (a(i+1) + a(i)) / 2 * dt; % Using trapezoidal rule
h(i+1) = h(i) + (v(i+1) + v(i)) / 2 * dt; % Using trapezoidal rule
last_i = i;
end
% Parachute Phase
for i = last_i:length(t)-1 % Resumes where previous loop finished
if h(i) < 0
break; % Stops loop when height is negative
end
%a(i) = -g;
a(i) = - g + (0.5 * rho * CD_Parachute * areaParachute * v(i)^2 / mTotal); % Drag / Mass = decelleration by drag
v(i+1) = v(i) + (a(i+1) + a(i)) / 2 * dt; % Using trapezoidal rule
h(i+1) = h(i) + (v(i+1) + v(i)) / 2 * dt; % Using trapezoidal rule
end
max_p = max(p);
min_p = min(p);
max_h = max(h);
min_h = min(h);
max_v = max(v);
min_v = min(v);
max_a = max(a);
min_a = min(a);
max_thrust = max(thrust);
min_thrust = min(thrust);
max_massCurrent = max(massCurrent);
min_massCurrent = min(massCurrent);
figure(1);
plot(t, p(1:length(t)),'LineWidth',1,'Color','k');
xlabel('Time (s)');
ylabel('Pressure (Pa)');
title('Rocket Pressure');
grid on;
xticks(0:5:t(end));
yticks(min_p-1e5:1e5:max_p+5e4);
ylim([min_p-1e5 max_p+5e4]);
text(t(end), max_p, sprintf('Max: %.2f', max_p), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'top');
text(t(end), min_p, sprintf('Min: %.2f', min_p), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
figure(2);
plot(t, h(1:length(t)),'LineWidth',1,'Color','k');
xlabel('Time (s)');
ylabel('Height (m)');
title('Rocket Height');
grid on;
xticks(0:5:t(end));
yticks(round(min_h,-1):10:round(max_h+5,-1));
ylim([min_h max_h+5]);
text(t(end), max_h, sprintf('Max: %.2f', max_h), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'top');
text(t(end), min_h, sprintf('Min: %.2f', min_h), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
figure(3);
plot(t, v(1:length(t)),'LineWidth',1,'Color','k');
xlabel('Time (s)');
ylabel('Velocity (m/s)');
title('Rocket Velocity');
grid on;
xticks(0:5:t(end));
yticks(round(min_v-5,-1):10:round(max_v+2,-1));
ylim([min_v-5 max_v+2]);
text(t(end), max_v, sprintf('Max: %.2f', max_v), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'top');
text(t(end), min_v, sprintf('Min: %.2f', min_v), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
figure(4);
plot(t, a(1:length(t)),'LineWidth',1,'Color','k');
xlabel('Time (s)');
ylabel('Acceleration (m/s^2)');
title('Rocket Acceleration');
grid on;
xticks(0:5:t(end));
yticks(round(min_a-10,-1):10:round(max_a+10,-1));
ylim([min_a-10 max_a+10]);
text(t(end), max_a, sprintf('Max: %.2f', max_a), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'top');
text(t(end), min_a, sprintf('Min: %.2f', min_a), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
figure(5);
plot(t, thrust(1:length(t)),'LineWidth',1,'Color','k');
xlabel('Time (s)');
ylabel('Thrust (N)');
title('Rocket Thrust');
grid on;
xticks(0:5:t(end));
yticks(round(min_thrust-10,-1):10:round(max_thrust+10,-1));
ylim([min_thrust-10 max_thrust+10]);
text(t(end), max_thrust, sprintf('Max: %.2f', max_thrust), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'top');
text(t(end), min_thrust, sprintf('Min: %.2f', min_thrust), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');
figure(6);
plot(t, massCurrent(1:length(t)),'LineWidth',1,'Color','k');
xlabel('Time (s)');
ylabel('Mass (kg)');
title('Total Rocket Mass (water included)');
grid on;
xticks(0:5:t(end));
yticks(0:0.2:round(max_massCurrent,1));
ylim([0 max_massCurrent]);
text(t(end), max_massCurrent, sprintf('Max: %.2f', max_massCurrent), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'top');
text(t(end), min_massCurrent, sprintf('Min: %.2f', min_massCurrent), 'HorizontalAlignment', 'right', 'VerticalAlignment', 'bottom');