Space Enterprise at Berkeley (Liquid Motor)#

Here we go with another flight simulation example using RocketPy. This time, we use data from the Space Enterprise at Berkeley team to perform a trajectory simulation using the LiquidMotor. Let’s check it out!

[1]:
# These lines are here for debugging purposes only
%load_ext autoreload
%autoreload 2
[2]:
from rocketpy import (
    Function,
    LiquidMotor,
    UllageBasedTank,
    MassBasedTank,
    Fluid,
    Rocket,
    Flight,
    Environment,
    CylindricalTank,
)

Input Curves#

First, we need to load the curves generated by the team during the motor testings.

The information that we are using are basically the volume of LOX and Propane in the tanks

[5]:
LOX_Volume_Liters = Function(
    "../../data/SEBLM/test124_Lox_Volume.csv", extrapolation="zero"
)
LOX_Volume = LOX_Volume_Liters * 0.001  # convert to m^3
LOX_Volume.set_discrete(8.003, 19.984, 40, interpolation="linear")
LOX_Volume.plot(force_data=True)
LOX_tank_ullage = 0.013167926436231077 - LOX_Volume
LOX_tank_ullage.plot(8, 8.5, force_data=True)
../_images/notebooks_SEBLM_6_0.png
../_images/notebooks_SEBLM_6_1.png
[7]:
Propane_Volume_Liters = Function("../../data/SEBLM/test124_Propane_Volume.csv")
Propane_Volume = Propane_Volume_Liters * 0.001  # convert to m^3
Propane_Volume.set_discrete(8.003, 19.984, 40, "linear")
Propane_Volume.plot(force_data=True)
Propane_tank_ullage = 0.013167926436231077 - Propane_Volume
Propane_tank_ullage.plot(force_data=True)
../_images/notebooks_SEBLM_7_0.png
../_images/notebooks_SEBLM_7_1.png

Fluids#

Now it’s time to define the fluids that we are going to use in the simulation.

[9]:
LOX = Fluid(name="LOX", density=1024)
Propane = Fluid(name="Propane", density=566)
LOXTankPressurizingGas = Fluid(name="N2", density=31.3 / 28)  # 450 PSI
PropaneTankPressurizingGas = Fluid(name="N2", density=313 * 300 / 4500 / 28)  # 300 PSI
PressurizingGas = Fluid(name="N2", density=313 / 28)  # 4500 PSI

Tanks#

After the fluids, it is time to define all the 3 tanks that we have in the motor.

LOX Tank#

We first start defining the tank geometry, which is a cylinder with a spherical head.

[10]:
LOX_tank_geometry = CylindricalTank(0.0744, 0.658, spherical_caps=True)

Next, we use the tank geometry to define the tank itself.

[11]:
LOX_tank = UllageBasedTank(
    name="LOX Tank",
    flux_time=(8, 20),
    geometry=LOX_tank_geometry,
    gas=LOXTankPressurizingGas,
    liquid=LOX,
    ullage=LOX_tank_ullage,
)

After defining, we stop for a minute to appreciate the evolution of mass and mass flow rate that were calculated by RocketPy.

Isn’t it beautiful?

[12]:
LOX_tank.fluid_mass()
LOX_tank.net_mass_flow_rate()
LOX_tank.liquid_height()
LOX_tank.gas_height()
LOX_tank.center_of_mass()
LOX_tank.inertia()
../_images/notebooks_SEBLM_19_0.png
../_images/notebooks_SEBLM_19_1.png
../_images/notebooks_SEBLM_19_2.png
../_images/notebooks_SEBLM_19_3.png
../_images/notebooks_SEBLM_19_4.png
../_images/notebooks_SEBLM_19_5.png

Propane Tank#

Our setup work is not done yet. We still need to define the propane tank, Which is a cylinder with a spherical head.

The propane has the role of pressurizing the LOX tank.

[13]:
Propane_tank_geometry = CylindricalTank(0.0744, 0.658, spherical_caps=True)
Propane_tank = UllageBasedTank(
    name="Propane Tank",
    flux_time=(8, 20),
    geometry=Propane_tank_geometry,
    gas=PropaneTankPressurizingGas,
    liquid=Propane,
    ullage=Propane_tank_ullage,
)

Again, let’s visualize the partial results.

[14]:
Propane_tank.fluid_mass()
Propane_tank.net_mass_flow_rate()
Propane_tank.liquid_height()
Propane_tank.gas_height()
Propane_tank.center_of_mass()
Propane_tank.inertia()
../_images/notebooks_SEBLM_24_0.png
../_images/notebooks_SEBLM_24_1.png
../_images/notebooks_SEBLM_24_2.png
../_images/notebooks_SEBLM_24_3.png
../_images/notebooks_SEBLM_24_4.png
../_images/notebooks_SEBLM_24_5.png

Pressure Tank#

The third tank is the pressure tank, which is a cylinder with a spherical head.

[15]:
Pressure_tank_geometry = CylindricalTank(0.135 / 2, 0.846, spherical_caps=True)
Pressure_tank = MassBasedTank(
    name="Pressure Tank",
    geometry=Pressure_tank_geometry,
    liquid_mass=0,
    flux_time=(8, 20),
    gas_mass="../../data/SEBLM/pressurantMassFiltered.csv",
    gas=PressurizingGas,
    liquid=PressurizingGas,
)
[16]:
Pressure_tank.fluid_mass()
Pressure_tank.net_mass_flow_rate()
Pressure_tank.liquid_height()
Pressure_tank.gas_height()
Pressure_tank.center_of_mass()
Pressure_tank.inertia()
../_images/notebooks_SEBLM_28_0.png
../_images/notebooks_SEBLM_28_1.png
../_images/notebooks_SEBLM_28_2.png
../_images/notebooks_SEBLM_28_3.png
../_images/notebooks_SEBLM_28_4.png
../_images/notebooks_SEBLM_28_5.png

Liquid Motor#

After defining the three tanks, we can finally define the liquid motor object, just check how simple it is!

[18]:
SEBLM = LiquidMotor(
    thrust_source="../../data/SEBLM/test124_Thrust_Curve.csv",
    center_of_dry_mass_position=0,
    dry_inertia=(0, 0, 0),
    dry_mass=0,
    burn_time=(8, 20),
    nozzle_radius=0.069 / 2,
    nozzle_position=-1.364,
    coordinate_system_orientation="nozzle_to_combustion_chamber",
)

SEBLM.add_tank(Propane_tank, position=-1.048)
SEBLM.add_tank(LOX_tank, position=0.711)
SEBLM.add_tank(Pressure_tank, position=2.007)

After defining it, we can check all the important information about the motor, such as the thrust curve, the mass flow rate curve, the specific impulse curve, and the burn time.

[19]:
SEBLM.all_info()
Nozzle Details
Nozzle Radius: 0.0345 m

Motor Details
Total Burning Time: 12 s
Total Propellant Mass: 19.852 kg
Average Propellant Exhaust Velocity: 1743.503 m/s
Average Thrust: 2064.885 N
Maximum Thrust: 2428.4243134124745 N at 17.666 s after ignition.
Total Impulse: 24778.624 Ns

c:\mateus\github\rocketpy\rocketpy\Function.py:2487: IntegrationWarning: The occurrence of roundoff error is detected, which prevents
  the requested tolerance from being achieved.  The error may be
  underestimated.
  ans, _ = integrate.quad(self, a, b, epsabs=0.001, limit=10000)
../_images/notebooks_SEBLM_33_2.png
../_images/notebooks_SEBLM_33_3.png
../_images/notebooks_SEBLM_33_4.png
../_images/notebooks_SEBLM_33_5.png
../_images/notebooks_SEBLM_33_6.png
../_images/notebooks_SEBLM_33_7.png
../_images/notebooks_SEBLM_33_8.png
../_images/notebooks_SEBLM_33_9.png
../_images/notebooks_SEBLM_33_10.png
../_images/notebooks_SEBLM_33_11.png
../_images/notebooks_SEBLM_33_12.png

Rocket Definition#

The motor is ready to go, but we still need to define the rocket itself. Let’s see how it is done:

[23]:
SEBRocket = Rocket(
    radius=0.098,
    mass=63.4,
    inertia=(25, 25, 1),
    power_off_drag="../../data/SEBLM/drag.csv",
    power_on_drag="../../data/SEBLM/drag.csv",
    center_of_mass_without_motor=3.23,
    coordinate_system_orientation="nose_to_tail",
)
SEBRocket.add_motor(SEBLM, position=5.75)
SEBRocket.add_nose(length=0.7, kind="vonKarman", position=0)
SEBRocket.add_tail(
    top_radius=0.098, bottom_radius=0.058, length=0.198, position=5.69 - 0.198
)

SEBRocket.add_trapezoidal_fins(
    n=4,
    root_chord=0.355,
    tip_chord=0.0803,
    span=0.156,
    position=5.25,
    cant_angle=0,
)

SEBRocket.set_rail_buttons(lower_button_position=-1, upper_button_position=1)
[23]:
<rocketpy.AeroSurface.RailButtons at 0x241c353b2b0>
[24]:
SEBRocket.all_info()

Inertia Details

Rocket Mass: 63.400 kg
Rocket Dry Mass: 63.400 kg (With Motor)
Rocket Mass: 83.252 kg (With Propellant)
Rocket Inertia (with motor, but without propellant) 11: 25.000 kg*m2
Rocket Inertia (with motor, but without propellant) 22: 25.000 kg*m2
Rocket Inertia (with motor, but without propellant) 33: 1.000 kg*m2
Rocket Inertia (with motor, but without propellant) 12: 0.000 kg*m2
Rocket Inertia (with motor, but without propellant) 13: 0.000 kg*m2
Rocket Inertia (with motor, but without propellant) 23: 0.000 kg*m2


Geometrical Parameters

Rocket Maximum Radius: 0.098 m
Rocket Frontal Area: 0.030172 m2

Rocket Distances
Rocket Center of Dry Mass - Center of Mass withour Motor: 0.000 m
Rocket Center of Dry Mass - Nozzle Exit Distance: 2.520 m
Rocket Center of Dry Mass - Center of Propellant Mass: 0.959 m
Rocket Center of Mass - Rocket Loaded Center of Mass: 0.229 m


Aerodynamics Lift Coefficient Derivatives

Nosecone Lift Coefficient Derivative: 2.000/rad
Tail Lift Coefficient Derivative: -1.299/rad
Fins Lift Coefficient Derivative: 5.895/rad

Aerodynamics Center of Pressure

Nosecone Center of Pressure to CM: 0.350 m
Tail Center of Pressure to CM: 5.583 m
Fins Center of Pressure to CM: 5.420 m
Distance - Center of Pressure to Center of Dry Mass: -0.392 m
Initial Static Margin: 2.000 c
Final Static Margin: 2.688 c



Mass Plots
../_images/notebooks_SEBLM_37_1.png
../_images/notebooks_SEBLM_37_2.png

Aerodynamics Plots
../_images/notebooks_SEBLM_37_4.png
../_images/notebooks_SEBLM_37_5.png
../_images/notebooks_SEBLM_37_6.png
../_images/notebooks_SEBLM_37_7.png

Environment#

I swear this is the last step before actually flying the rocket. We need to define the environment in which the rocket will fly.

[25]:
env = Environment(
    latitude=35.347122986338356, longitude=-117.80893423073582
)

env.set_date((2022, 12, 3, 14 + 7, 0, 0))  # UTC

env.set_atmospheric_model(
    type="custom_atmosphere",
    pressure=None,
    temperature=None,
    wind_u=[(0, 1), (500, 0), (1000, 5), (2500, 5.0), (5000, 10)],
    wind_v=[(0, 0), (500, 3), (1600, 2), (2500, -3), (5000, 10)],
)

env.maxExpectedHeight = 8000
[26]:
env.info()

Gravity Details

Acceleration of Gravity at Lauch Site: 9.797631455625396 m/s²


Launch Site Details

Launch Date: 2022-12-03 21:00:00 UTC
Launch Site Latitude: 35.34712°
Launch Site Longitude: -117.80893°
Reference Datum: SIRGAS2000
Launch Site UTM coordinates: 426495.69 W    3911838.99 N
Launch Site UTM zone: 11S
Launch Site Surface Elevation: 0.0 m


Atmospheric Model Details

Atmospheric Model Type: custom_atmosphere
custom_atmosphere Maximum Height: 5.000 km


Surface Atmospheric Conditions

Surface Wind Speed: 1.00 m/s
Surface Wind Direction: 270.00°
Surface Wind Heading: 90.00°
Surface Pressure: 1013.25 hPa
Surface Temperature: 288.15 K
Surface Air Density: 1.225 kg/m³
Surface Speed of Sound: 340.29 m/s


Atmospheric Model Plots

../_images/notebooks_SEBLM_41_1.png

Flight Simulation#

Finally, here we go with our flight simulation. We are going to run the simulation only until the apogee, since we are not interested in the landing phase.

The maxTimeStep parameter was set to a low value to ensure there won’t be any numerical instability during the launch rail phase.

[28]:
test_flight = Flight(
    rocket=SEBRocket,
    environment=env,
    rail_length=18.28,
    inclination=90,
    heading=23,
    max_time_step=0.1,
    terminate_on_apogee=True,
)
[30]:
test_flight.angle_of_attack.plot(test_flight.out_of_rail_time, 15)
../_images/notebooks_SEBLM_45_0.png
[31]:
test_flight.all_info()

Initial Conditions

Position - x: 0.00 m | y: 0.00 m | z: 0.00 m
Velocity - Vx: 0.00 m/s | Vy: 0.00 m/s | Vz: 0.00 m/s
Attitude - e0: 0.980 | e1: 0.000 | e2: -0.000 | e3: -0.199
Euler Angles - Spin φ : -191.50° | Nutation θ: -0.00° | Precession ψ: 168.50°
Angular Velocity - ω1: 0.00 rad/s | ω2: 0.00 rad/s| ω3: 0.00 rad/s


Surface Wind Conditions

Frontal Surface Wind Speed: 0.39 m/s
Lateral Surface Wind Speed: -0.92 m/s


Launch Rail

Launch Rail Length: 18.28  m
Launch Rail Inclination: 90.00°
Launch Rail Heading: 23.00°


Rail Departure State

Rail Departure Time: 9.434 s
Rail Departure Velocity: 19.708 m/s
Rail Departure Static Margin: 2.029 c
Rail Departure Angle of Attack: 2.831°
Rail Departure Thrust-Weight Ratio: 2.252
Rail Departure Reynolds Number: 2.645e+05


Burn out State

Burn out time: 20.000 s
Altitude at burn out: 1094.550 m (AGL)
Rocket velocity at burn out: 199.214 m/s
Freestream velocity at burn out: 199.811 m/s
Mach Number at burn out: 0.595
Kinetic energy at burn out: 1.328e+06 J


Apogee State

Apogee Altitude: 2799.897 m (ASL) | 2799.897 m (AGL)
Apogee Time: 38.205 s
Apogee Freestream Speed: 18.930 m/s


Parachute Events

No Parachute Events Were Triggered.


Impact Conditions

X Impact: 0.000 m
Y Impact: 0.000 m
Time of Impact: 38.205 s
Velocity at Impact: 0.000 m/s


Maximum Values

Maximum Speed: 199.214 m/s at 20.00 s
Maximum Mach Number: 0.595 Mach at 20.00 s
Maximum Reynolds Number: 2.461e+06 at 20.00 s
Maximum Dynamic Pressure: 2.199e+04 Pa at 20.00 s
Maximum Acceleration: 21.624 m/s² at 17.38 s
Maximum Gs: 2.207 g at 17.38 s
Maximum Upper Rail Button Normal Force: 1.606 N
Maximum Upper Rail Button Shear Force: -0.045 N
Maximum Lower Rail Button Normal Force: 0.636 N
Maximum Lower Rail Button Shear Force: -0.017 N


Numerical Integration Settings

Maximum Allowed Flight Time: 600.000000 s
Maximum Allowed Time Step: 0.100000 s
Minimum Allowed Time Step: 0.000000e+00 s
Relative Error Tolerance:  1e-06
Absolute Error Tolerance:  [0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 1e-06, 1e-06, 1e-06, 1e-06, 0.001, 0.001, 0.001]
Allow Event Overshoot:  True
Terminate Simulation on Apogee:  True
Number of Time Steps Used:  707
Number of Derivative Functions Evaluation:  1653
Average Function Evaluations per Time Step: 2.338048



Trajectory 3d Plot

../_images/notebooks_SEBLM_46_1.png


Trajectory Kinematic Plots

../_images/notebooks_SEBLM_46_3.png


Angular Position Plots

../_images/notebooks_SEBLM_46_5.png


Path, Attitude and Lateral Attitude Angle plots

../_images/notebooks_SEBLM_46_7.png


Trajectory Angular Velocity and Acceleration Plots

../_images/notebooks_SEBLM_46_9.png


Aerodynamic Forces Plots

../_images/notebooks_SEBLM_46_11.png


Rail Buttons Forces Plots

../_images/notebooks_SEBLM_46_13.png


Trajectory Energy Plots

../_images/notebooks_SEBLM_46_15.png


Trajectory Fluid Mechanics Plots

../_images/notebooks_SEBLM_46_17.png


Trajectory Stability and Control Plots

../_images/notebooks_SEBLM_46_19.png


Rocket and Parachute Pressure Plots

../_images/notebooks_SEBLM_46_21.png

Rocket has no parachutes. No parachute plots available