From 59e26ec81689247e38ba051b2f9104b76ae094f6 Mon Sep 17 00:00:00 2001 From: GabrielBarberini Date: Mon, 2 Sep 2024 21:03:18 -0300 Subject: [PATCH] exposes motor tank property and disable fronzen instances --- lib/models/aerosurfaces.py | 52 ++++++++++++++++++------------------- lib/models/environment.py | 2 +- lib/models/flight.py | 2 +- lib/models/motor.py | 42 +++++++++++++++++------------- lib/models/parachute.py | 14 +++++----- lib/models/rocket.py | 53 ++++++++++++++++++++++++++++---------- lib/routes/motor.py | 1 + lib/services/motor.py | 4 ++- lib/services/rocket.py | 13 ++-------- 9 files changed, 104 insertions(+), 79 deletions(-) diff --git a/lib/models/aerosurfaces.py b/lib/models/aerosurfaces.py index 0dff121..1a88fbc 100644 --- a/lib/models/aerosurfaces.py +++ b/lib/models/aerosurfaces.py @@ -2,38 +2,38 @@ from pydantic import BaseModel -class RailButtons(BaseModel, frozen=True): - upper_button_position: Optional[float] = -0.5 - lower_button_position: Optional[float] = 0.2 - angular_position: Optional[float] = 45 +class RailButtons(BaseModel): + upper_button_position: float + lower_button_position: float + angular_position: float -class NoseCone(BaseModel, frozen=True): - length: float = 0.55829 - kind: str = "vonKarman" - position: float = 1.278 - base_radius: float = 0.0635 - rocket_radius: float = 0.0635 +class NoseCone(BaseModel): + length: float + kind: str + position: float + base_radius: float + rocket_radius: float -class Fins(BaseModel, frozen=True): - n: int = 4 - root_chord: float = 0.12 - tip_chord: float = 0.04 - span: float = 0.1 - position: float = -1.04956 - cant_angle: float = 0 - radius: float = 0.0635 - airfoil: str = "" +class Fins(BaseModel): + n: int + root_chord: float + tip_chord: float + span: float + position: float + cant_angle: float + radius: float + airfoil: str -class TrapezoidalFins(Fins, frozen=True): +class TrapezoidalFins(Fins): pass -class Tail(BaseModel, frozen=True): - top_radius: float = 0.0635 - bottom_radius: float = 0.0435 - length: float = 0.06 - position: float = -1.194656 - radius: float = 0.0635 +class Tail(BaseModel): + top_radius: float + bottom_radius: float + length: float + position: float + radius: float diff --git a/lib/models/environment.py b/lib/models/environment.py index cd2b9ab..07c08c6 100644 --- a/lib/models/environment.py +++ b/lib/models/environment.py @@ -3,7 +3,7 @@ from pydantic import BaseModel -class Env(BaseModel, frozen=True): +class Env(BaseModel): latitude: float = 0 longitude: float = 0 elevation: Optional[int] = 1400 diff --git a/lib/models/flight.py b/lib/models/flight.py index 61343cc..0930a4f 100644 --- a/lib/models/flight.py +++ b/lib/models/flight.py @@ -3,7 +3,7 @@ from lib.models.environment import Env -class Flight(BaseModel, frozen=True): +class Flight(BaseModel): environment: Env = Env() rocket: Rocket = Rocket() inclination: int = 85 diff --git a/lib/models/motor.py b/lib/models/motor.py index 325cb5a..c78b101 100644 --- a/lib/models/motor.py +++ b/lib/models/motor.py @@ -1,5 +1,5 @@ from enum import Enum -from typing import Optional, Tuple, List +from typing import Optional, Tuple, List, Union from rocketpy import ( LevelBasedTank, MassBasedTank, @@ -28,37 +28,41 @@ class TankKinds(str, Enum): ULLAGE: str = "ULLAGE" -class TankFluids(BaseModel, frozen=True): - name: str = "FLUIDNAME" - density: float = 100.0 +class TankFluids(BaseModel): + name: str + density: float -class MotorTank(BaseModel, frozen=True): +class MotorTank(BaseModel): # Required parameters geometry: List[Tuple[Tuple[float, float], float]] = [ - ((0, 5), 1), - ((5, 10), 2), + ((0.0, 5.0), 1.0), + ((5.0, 10.0), 2.0), ] tank_kind: TankKinds = TankKinds.MASS_FLOW - gas: TankFluids = TankFluids() - liquid: TankFluids = TankFluids() + gas: TankFluids = TankFluids(name="GAS", density=100) + liquid: TankFluids = TankFluids(name="LIQUID", density=1000) name: str = "Tank" - flux_time: List[float] = [0.0, 8.0] + flux_time: Tuple[float, float] = (0.0, 3.9) position: float = 1.0 + discretize: int = 100 # Optional parameters - discretize: Optional[int] = 100 liquid_height: Optional[float] = 0.5 liquid_mass: Optional[float] = 5.0 gas_mass: Optional[float] = 0.1 - gas_mass_flow_rate_in: Optional[float] = 0.1 + gas_mass_flow_rate_in: Optional[float] = 0.0 gas_mass_flow_rate_out: Optional[float] = 0.1 - liquid_mass_flow_rate_in: Optional[float] = 0.1 - liquid_mass_flow_rate_out: Optional[float] = 0.1 + liquid_mass_flow_rate_in: Optional[float] = 0.0 + liquid_mass_flow_rate_out: Optional[float] = 1 initial_liquid_mass: Optional[float] = 5.0 - initial_gas_mass: Optional[float] = 0.1 + initial_gas_mass: Optional[float] = 0.4 ullage: Optional[float] = 0.1 + _tank: Union[ + LevelBasedTank, MassBasedTank, MassFlowRateBasedTank, UllageBasedTank + ] = PrivateAttr() + def __init__(self, **kwargs): super().__init__(**kwargs) tank_core = { @@ -93,12 +97,14 @@ def __init__(self, **kwargs): ) case TankKinds.ullage: tank = UllageBasedTank(**tank_core, ullage=self.ullage) - object.__setattr__(self, "tank", tank) + self._tank = tank + @property + def tank(self): + return self._tank -class Motor(BaseModel, frozen=True): - # TODO: thrust_source must be the id of a previously uploaded .eng file and a list of "default" files must be provided in the api docs +class Motor(BaseModel): # Required parameters thrust_source: MotorEngines = MotorEngines.CESARONI_M1670 burn_time: float = 3.9 diff --git a/lib/models/parachute.py b/lib/models/parachute.py index 4f9d384..42cc13d 100644 --- a/lib/models/parachute.py +++ b/lib/models/parachute.py @@ -2,13 +2,13 @@ from pydantic import BaseModel -class Parachute(BaseModel, frozen=True): - name: "List[str]" = ["Main", "Drogue"] - cd_s: "List[float]" = [10, 1] - lag: "List[float]" = [1.5, 1.5] - sampling_rate: "List[int]" = [105, 105] - noise: "List[Tuple[float, float, float]]" = [(0, 8.3, 0.5), (0, 8.3, 0.5)] - triggers: "List[str]" = [ +class Parachute(BaseModel): + name: List[str] = ["Main", "Drogue"] + cd_s: List[float] = [10, 1] + lag: List[float] = [1.5, 1.5] + sampling_rate: List[int] = [105, 105] + noise: List[Tuple[float, float, float]] = [(0, 8.3, 0.5), (0, 8.3, 0.5)] + triggers: List[str] = [ "lambda p, h, y: y[5] < 0 and h < 800", "lambda p, h, y: y[5] < 0", ] diff --git a/lib/models/rocket.py b/lib/models/rocket.py index a0102d9..60d2173 100644 --- a/lib/models/rocket.py +++ b/lib/models/rocket.py @@ -11,33 +11,58 @@ class RocketOptions(str, Enum): CUSTOM: str = "CUSTOM" -class Rocket(BaseModel, frozen=True): +class Rocket(BaseModel): # Required parameters - rail_buttons: RailButtons = RailButtons() motor: Motor = Motor() - nose: NoseCone = NoseCone() - fins: Fins = Fins() - tail: Tail = Tail() - parachutes: Parachute = Parachute() - inertia: Tuple[float, float, float] = (6.321, 6.321, 0.0346) - center_of_mass_without_motor: int = 0 radius: float = 0.0632 mass: float = 16.235 motor_position: float = -1.255 - power_off_drag: List[Tuple[float, float]] = [ + parachutes: Parachute = Parachute() + center_of_mass_without_motor: int = 0 + inertia: Tuple[float, float, float] = (6.321, 6.321, 0.0346) + rail_buttons: RailButtons = RailButtons( + upper_button_position=-0.5, + lower_button_position=0.2, + angular_position=45, + ) + nose: NoseCone = NoseCone( + length=0.55829, + kind="vonKarman", + position=1.278, + base_radius=0.0635, + rocket_radius=0.0635, + ) + fins: Fins = Fins( + n=4, + root_chord=0.12, + tip_chord=0.04, + span=0.1, + position=-1.04956, + cant_angle=0, + radius=0.0635, + airfoil="", + ) + tail: Tail = Tail( + top_radius=0.0635, + bottom_radius=0.0435, + length=0.06, + position=-1.194656, + radius=0.0635, + ) + _rocket_option: RocketOptions = PrivateAttr(default=RocketOptions.CALISTO) + + # Optional parameters + # TODO: implement field validation so a list of possible tailToNose values is provided in the api docs + power_off_drag: Optional[List[Tuple[float, float]]] = [ (0.01, 0.333865758), (0.02, 0.394981721), (0.03, 0.407756063), ] - power_on_drag: List[Tuple[float, float]] = [ + power_on_drag: Optional[List[Tuple[float, float]]] = [ (0.01, 0.333865758), (0.02, 0.394981721), (0.03, 0.407756063), ] - _rocket_option: RocketOptions = PrivateAttr(default=RocketOptions.CALISTO) - - # Optional parameters - # TODO: implement field validation so a list of possible tailToNose values is provided in the api docs coordinate_system_orientation: Optional[str] = "tail_to_nose" @property diff --git a/lib/routes/motor.py b/lib/routes/motor.py index 5a0ecf2..faa0f21 100644 --- a/lib/routes/motor.py +++ b/lib/routes/motor.py @@ -26,6 +26,7 @@ tracer = trace.get_tracer(__name__) + @router.post("/") async def create_motor(motor: Motor, motor_kind: MotorKinds) -> MotorCreated: """ diff --git a/lib/services/motor.py b/lib/services/motor.py index 58b85a5..ee60a8e 100644 --- a/lib/services/motor.py +++ b/lib/services/motor.py @@ -19,7 +19,9 @@ def from_motor_model(cls, motor: Motor) -> Self: """ motor_core = { - "thrust_source": f"lib/data/engines/{motor.thrust_source.value}.eng", + "thrust_source": ( + f"lib/data/engines/{motor.thrust_source.value}.eng" + ), "burn_time": motor.burn_time, "nozzle_radius": motor.nozzle_radius, "dry_mass": motor.dry_mass, diff --git a/lib/services/rocket.py b/lib/services/rocket.py index 74ca2c9..d3cd527 100644 --- a/lib/services/rocket.py +++ b/lib/services/rocket.py @@ -1,4 +1,3 @@ -import os import ast from typing import Self from rocketpy.rocket.rocket import Rocket as RocketPyRocket @@ -32,16 +31,8 @@ def from_rocket_model(cls, rocket: Rocket) -> Self: radius=rocket.radius, mass=rocket.mass, inertia=rocket.inertia, - power_off_drag=os.path.join( - "lib/data", - f"{rocket.rocket_option.lower()}", - "powerOffDragCurve.csv", - ), - power_on_drag=os.path.join( - "lib/data", - f"{rocket.rocket_option.lower()}", - "powerOnDragCurve.csv", - ), + power_off_drag=rocket.power_off_drag, + power_on_drag=rocket.power_on_drag, center_of_mass_without_motor=rocket.center_of_mass_without_motor, coordinate_system_orientation=rocket.coordinate_system_orientation, )