From 521da01f6da6c32ccd834c20b7ea457a619361c8 Mon Sep 17 00:00:00 2001 From: Baitinq Date: Sun, 6 Feb 2022 22:52:22 +0000 Subject: Initial Commit --- .gitignore | 1 + atmosphere.py | 14 ++++++++++ body.py | 21 +++++++++++++++ engine.py | 7 +++++ fuel.py | 4 +++ main.py | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ rocket.py | 33 +++++++++++++++++++++++ simulation.py | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ universe.py | 8 ++++++ 9 files changed, 257 insertions(+) create mode 100644 .gitignore create mode 100644 atmosphere.py create mode 100644 body.py create mode 100644 engine.py create mode 100644 fuel.py create mode 100644 main.py create mode 100644 rocket.py create mode 100644 simulation.py create mode 100644 universe.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/atmosphere.py b/atmosphere.py new file mode 100644 index 0000000..48f9bd1 --- /dev/null +++ b/atmosphere.py @@ -0,0 +1,14 @@ +import math + +class Atmosphere(): + def __init__(self, avg_sea_level_pressure: int, molar_mass_air: float, standard_temp: float): + self.avg_sea_level_pressure = avg_sea_level_pressure + self.molar_mass_air = molar_mass_air + self.standard_temp = standard_temp + + #https://math24.net/barometric-formula.html + def density_at_height(self, height: int, g: float) -> None: + R = 8.3144598 #universal gas constant + pressure = self.avg_sea_level_pressure * math.e ** (-(self.molar_mass_air * g * height)/(R * self.standard_temp)) + density = pressure / (R * 10000) + return density \ No newline at end of file diff --git a/body.py b/body.py new file mode 100644 index 0000000..3be2c5e --- /dev/null +++ b/body.py @@ -0,0 +1,21 @@ +import math + +from atmosphere import Atmosphere + +class Body(): + def __init__(self, name: str, density: int, radius: int, atmosphere: type[Atmosphere]): + self.name = name + self.density = density + self.radius = radius + self.atmosphere = atmosphere + + def mass(self): + body_volume = (4/3) * math.pi * (self.radius**3) + return body_volume * self.density * 1000 + + def g(self, G: float, height: int): + return (G * self.mass()) / ((self.radius + height) ** 2) + + + def __str__(self): + return "uwu" \ No newline at end of file diff --git a/engine.py b/engine.py new file mode 100644 index 0000000..26a5bab --- /dev/null +++ b/engine.py @@ -0,0 +1,7 @@ +import fuel + +class Engine(): + def __init__(self, name: str, thrust: int, flow_rate: float): + self.name = name + self.thrust = thrust + self.flow_rate = flow_rate \ No newline at end of file diff --git a/fuel.py b/fuel.py new file mode 100644 index 0000000..11fc233 --- /dev/null +++ b/fuel.py @@ -0,0 +1,4 @@ +class Fuel(): + def __init__(self, name: str, energy_density: float): + self.name = name + self.energy_density = energy_density \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..d322193 --- /dev/null +++ b/main.py @@ -0,0 +1,84 @@ +import sys +import math +from time import sleep + +from engine import Engine +from fuel import Fuel +from rocket import Rocket +from atmosphere import Atmosphere +from body import Body +from universe import Universe +from simulation import Simulation + +import pygame +from pygame.locals import * + +def main(argv): + rocket = Rocket(name="starship", + rocket_mass=240000, #thrust=245000 + engine=Engine(name="raptor", thrust=2.3E6, flow_rate=1000), #https://en.wikipedia.org/wiki/SpaceX_Raptor + engine_number=33, + fuel_type=Fuel(name="methane", energy_density=None), + fuel_mass=4000000, + drag_coefficient=1.18, + cross_sectional_area=(math.pi * (9**2)) + ) + + body = Body(name="earth", + density=5.51, + radius=6371000, + atmosphere=Atmosphere( + avg_sea_level_pressure=101325, + molar_mass_air=0.02896, + standard_temp=288.15 + ) + ) + + universe = Universe(name="conventional", + G=6.67E-11, + plank=None + ) + + simulation = Simulation(universe, body, rocket) + + pygame.init() + simulation_display = pygame.display.set_mode((400,500)) + while(True): + delta = 0.01 + sleep(delta) + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + quit() + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_SPACE: + simulation.rocket.engines_on = not simulation.rocket.engines_on + elif event.key == pygame.K_LEFT: + sys.exit(0) + elif event.key == pygame.K_RIGHT: + sys.exit(0) + + simulation.tick(delta=delta) + draw_simulation(simulation_display, simulation) + + pygame.display.update() + + #TODO: do max load on rocket so it blows up + #TODO: display sim info on screen + #TODO: allow for x movement, speed, accel etc + #TODO: draw floor, flame + #TODO: allow multilanguage api for landing algorithms etc + +def draw_simulation(simulation_display: type[pygame.Surface], simulation: type[Simulation]) -> None: + simulation_display.fill(get_color_for_height(simulation.y)) #gradient for atmosphere TODO + + pygame.draw.rect(simulation_display, (0, 125, 255), pygame.Rect(30, 30, 60, 60)) + if simulation.rocket.engines_on: + pygame.draw.circle(simulation_display, (255, 125, 100), (60, 100), 10) + +def get_color_for_height(height: int) -> (int, int, int): + return (255, 255, 255) + +if __name__ == "__main__": + main(sys.argv) \ No newline at end of file diff --git a/rocket.py b/rocket.py new file mode 100644 index 0000000..eb73c7c --- /dev/null +++ b/rocket.py @@ -0,0 +1,33 @@ +from engine import Engine +from fuel import Fuel + +class Rocket(): + def __init__(self, name: str, rocket_mass: int, engine: type[Engine], engine_number: int, fuel_type: type[Fuel], fuel_mass: int, drag_coefficient: float, cross_sectional_area: float): + self.name = name + self.rocket_mass = rocket_mass + self.engine = engine + self.engine_number = engine_number + self.fuel_type = fuel_type + self.fuel_mass = fuel_mass + self.drag_coefficient = drag_coefficient + self.cross_sectional_area = cross_sectional_area + + self.engines_on = True + + def total_mass(self): + return self.rocket_mass + self.fuel_mass + + def total_thrust(self): + if(self.engines_on): + return self.engine.thrust * self.engine_number + else: + return 0 + + def total_fuel_used(self, delta: int): + if(self.engines_on): + return self.engine.flow_rate * self.engine_number * delta + else: + return 0 + + def __str__(self): + return "eue" \ No newline at end of file diff --git a/simulation.py b/simulation.py new file mode 100644 index 0000000..a93a263 --- /dev/null +++ b/simulation.py @@ -0,0 +1,85 @@ +from dataclasses import dataclass + +from universe import Universe +from body import Body +from rocket import Rocket + +@dataclass +class Simulation_Snapshot: + universe: type[Universe] + body: type[Body] + rocket: type[Rocket] + +class Simulation(): + def __init__(self, universe: type[Universe], body: type[Body], rocket: type[Rocket]): + self.ticks = 0 + self.time = 0 + self.universe = universe + self.body = body + self.rocket = rocket + self.y = 0 + self.speed_y = 0 + + #simulation logic + def tick(self, delta: int) -> None: + #calculate upwards force by fuel + # TODO able to turn engine on and off + fuel_used = self.rocket.total_fuel_used(delta) + if self.rocket.fuel_mass < fuel_used: + fuel_used = self.rocket.fuel_mass + self.rocket.fuel_mass -= fuel_used + print("Fuel remaining: " + str(self.rocket.fuel_mass)) + + #upwards_force = fuel_used * self.rocket.fuel_type.energy_density #we should calculate thrust based on this + upwards_force = 0 + if fuel_used > 0: + upwards_force = self.rocket.total_thrust() + print("Upwards force: " + str(upwards_force)) + + print("g: " + str(self.body.g(G=self.universe.G, height=self.y))) + + #calculate downwards force by drag and gravity + gravitational_force = self.body.g(G=self.universe.G, height=self.y) * self.rocket.total_mass() + print("Gravity: " + str(gravitational_force)) + + print("BODY MASS: " + str(self.body.mass())) + print("ROCKET TOTAL MASS: " + str(self.rocket.total_mass())) + + print("Atmosphere density: " + str(self.body.atmosphere.density_at_height(self.y, self.body.g(G=self.universe.G, height=self.y)))) + + #https://www.grc.nasa.gov/www/k-12/airplane/drageq.html + drag_force = (1/2) * self.body.atmosphere.density_at_height(self.y, self.body.g(G=self.universe.G, height=self.y)) * (self.speed_y ** 2) * self.rocket.drag_coefficient * self.rocket.cross_sectional_area + print("Drag: " + str(drag_force)) #drag can be negative too? + + downwards_force = gravitational_force + drag_force #shouldnt delta influence, TODO: WAIT DRAG COULD BE POSITIVE OR NEGATIVE + print("Downwards force: " + str(downwards_force)) + + #update velocity based on resultant force + total_force = upwards_force - downwards_force + print("Total force: " + str(total_force)) + + acceleration = total_force / self.rocket.total_mass() #mayb we need momentum?? + print("Acceleration: " + str(acceleration)) + self.speed_y = self.speed_y + (acceleration * delta) #i think thir swrong + + #update position based on velocity and delta + self.y += self.speed_y * delta + if self.y < 0: + self.y = 0 + self.speed_y = 0 + + print("Speed: " + str(self.speed_y)) + print("Height: " + str(self.y)) + + print("") + + self.ticks += 1 + self.time += delta + + def snapshot(self) -> Simulation_Snapshot: + return Simulation_Snapshot(self.universe, self.body, self.rocket) + + def str_snapshot(self) -> str: + return str(self.universe) + "\n" + \ + str(self.body) + "\n" + \ + str(self.rocket) \ No newline at end of file diff --git a/universe.py b/universe.py new file mode 100644 index 0000000..2d859e8 --- /dev/null +++ b/universe.py @@ -0,0 +1,8 @@ +class Universe(): + def __init__(self, name: str, G: float, plank: float): + self.name = name + self.G = G + self.plank = plank + + def __str__(self): + return "kuu" \ No newline at end of file -- cgit 1.4.1