Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def custom_openapi():
return app.openapi_schema
openapi_schema = get_openapi(
title="RocketPy Infinity-API",
version="2.1.0",
version="2.2.0",
description=(
"<p style='font-size: 18px;'>RocketPy Infinity-API is a RESTful Open API for RocketPy, a rocket flight simulator.</p>"
"<br/>"
Expand Down
21 changes: 16 additions & 5 deletions lib/models/aerosurfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


class RailButtons(BaseModel):
name: str
name: str = "RailButtons"
upper_button_position: float
lower_button_position: float
angular_position: float
Expand Down Expand Up @@ -34,12 +34,23 @@ class Fins(BaseModel):
name: str
n: int
root_chord: float
tip_chord: Optional[float]
span: float
position: float
cant_angle: float
radius: float
airfoil: Tuple[List[Tuple[float, float]], AngleUnit]

# Optional parameters
tip_chord: Optional[float] = None
cant_angle: Optional[float] = None
rocket_radius: Optional[float] = None
airfoil: Optional[Tuple[List[Tuple[float, float]], AngleUnit]] = None

def get_additional_parameters(self):
return {
key: value
for key, value in self.dict().items()
if value is not None
and key
not in ["fins_kind", "name", "n", "root_chord", "span", "position"]
}


# TODO: implement airbrakes
Expand Down
24 changes: 18 additions & 6 deletions lib/models/environment.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import datetime
from enum import Enum
from typing import Optional
from pydantic import BaseModel


class AtmosphericModelTypes(str, Enum):
STANDARD_ATMOSPHERE: str = "STANDARD_ATMOSPHERE"
CUSTOM_ATMOSPHERE: str = "CUSTOM_ATMOSPHERE"
WYOMING_SOUNDING: str = "WYOMING_SOUNDING"
FORECAST: str = "FORECAST"
REANALYSIS: str = "REANALYSIS"
ENSEMBLE: str = "ENSEMBLE"


class Env(BaseModel):
latitude: float = 0
longitude: float = 0
elevation: Optional[int] = 1400
latitude: float
longitude: float
elevation: Optional[int] = 1

# Opional parameters
atmospheric_model_type: Optional[str] = "standard_atmosphere"
atmospheric_model_file: Optional[str] = "GFS"
# Optional parameters
atmospheric_model_type: AtmosphericModelTypes = (
AtmosphericModelTypes.STANDARD_ATMOSPHERE
)
atmospheric_model_file: Optional[str] = None
date: Optional[datetime.datetime] = (
datetime.datetime.today() + datetime.timedelta(days=1)
)
53 changes: 35 additions & 18 deletions lib/models/flight.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,43 @@


class EquationsOfMotion(str, Enum):
STANDARD = "STANDARD"
SOLID_PROPULSION = "SOLID_PROPULSION"
STANDARD: str = "STANDARD"
SOLID_PROPULSION: str = "SOLID_PROPULSION"


class Flight(BaseModel):
name: str = "Flight"
environment: Env = Env()
rocket: Rocket = Rocket()
rail_length: float = 5.2
inclination: Optional[int] = 80.0
heading: Optional[int] = 90.0
environment: Env
rocket: Rocket
rail_length: float = 1
time_overshoot: bool = True
terminate_on_apogee: bool = True
equations_of_motion: EquationsOfMotion = EquationsOfMotion.STANDARD

# Optional parameters
inclination: Optional[int] = None
heading: Optional[int] = None
# TODO: implement initial_solution
terminate_on_apogee: Optional[bool] = False
max_time: Optional[int] = 600
max_time_step: Optional[float] = 9999
min_time_step: Optional[int] = 0
rtol: Optional[float] = 1e-3
atol: Optional[float] = 1e-3
time_overshoot: Optional[bool] = True
verbose: Optional[bool] = False
equations_of_motion: Optional[EquationsOfMotion] = (
EquationsOfMotion.STANDARD
)
max_time: Optional[int] = None
max_time_step: Optional[float] = None
min_time_step: Optional[int] = None
rtol: Optional[float] = None
atol: Optional[float] = None
verbose: Optional[bool] = None

def get_additional_parameters(self):
return {
key: value
for key, value in self.dict().items()
if value is not None
and key
not in [
"name",
"environment",
"rocket",
"rail_length",
"time_overshoot",
"terminate_on_apogee",
"equations_of_motion",
]
}
96 changes: 51 additions & 45 deletions lib/models/motor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from enum import Enum
from typing import Optional, Tuple, List
from typing import Optional, Tuple, List, Union
from pydantic import BaseModel, PrivateAttr


Expand All @@ -13,7 +13,7 @@ class MotorKinds(str, Enum):
class TankKinds(str, Enum):
LEVEL: str = "LEVEL"
MASS: str = "MASS"
MASS_FLOW: str = "MASSFlOW"
MASS_FLOW: str = "MASSFLOW"
ULLAGE: str = "ULLAGE"


Expand All @@ -27,80 +27,86 @@ class TankFluids(BaseModel):
density: float


class InterpolationMethods(str, Enum):
LINEAR: str = "LINEAR"
SPLINE: str = "SPLINE"
AKIMA: str = "AKIMA"
POLYNOMIAL: str = "POLYNOMIAL"
SHEPARD: str = "SHEPARD"
RBF: str = "RBF"


class MotorTank(BaseModel):
# Required parameters
geometry: List[Tuple[Tuple[float, float], float]] = [
((0.0, 5.0), 1.0),
((5.0, 10.0), 2.0),
]
gas: TankFluids = TankFluids(name="GAS", density=100)
liquid: TankFluids = TankFluids(name="LIQUID", density=1000)
flux_time: Tuple[float, float] = (0.0, 3.9)
position: float = 1.0
discretize: int = 100
geometry: List[Tuple[Tuple[float, float], float]]
gas: TankFluids
liquid: TankFluids
flux_time: Tuple[float, float]
position: float
discretize: int

# Level based tank parameters
liquid_height: Optional[float] = 0.5
liquid_height: Optional[float]

# Mass based tank parameters
liquid_mass: Optional[float] = 5.0
gas_mass: Optional[float] = 0.1
liquid_mass: Optional[float]
gas_mass: Optional[float]

# Mass flow based tank parameters
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.0
liquid_mass_flow_rate_out: Optional[float] = 1
initial_liquid_mass: Optional[float] = 5.0
initial_gas_mass: Optional[float] = 0.4
gas_mass_flow_rate_in: Optional[float]
gas_mass_flow_rate_out: Optional[float]
liquid_mass_flow_rate_in: Optional[float]
liquid_mass_flow_rate_out: Optional[float]
initial_liquid_mass: Optional[float]
initial_gas_mass: Optional[float]

# Ullage based tank parameters
ullage: Optional[float] = 0.1
ullage: Optional[float]

# Optional parameters
name: Optional[str] = "Tank"
name: Optional[str]

# Computed parameters
tank_kind: TankKinds = TankKinds.MASS_FLOW


class Motor(BaseModel):
# Required parameters
thrust_source: List[List[float]] = [[0.0, 0.0], [1.0, 1.0]]
burn_time: float = 3.9
nozzle_radius: float = 0.033
dry_mass: float = 1.815
dry_inertia: Tuple[float, float, float] = (0.125, 0.125, 0.002)
center_of_dry_mass_position: float = 0.317
thrust_source: List[List[float]]
burn_time: float
nozzle_radius: float
dry_mass: float
dry_inertia: Tuple[float, float, float] = (0, 0, 0)
center_of_dry_mass_position: float

# Generic motor parameters
chamber_radius: Optional[float] = 0.033
chamber_height: Optional[float] = 0.1
chamber_position: Optional[float] = 0.0
propellant_initial_mass: Optional[float] = 1.0
nozzle_position: Optional[float] = 0.0
chamber_radius: Optional[float] = None
chamber_height: Optional[float] = None
chamber_position: Optional[float] = None
propellant_initial_mass: Optional[float] = None
nozzle_position: Optional[float] = None

# Liquid motor parameters
tanks: Optional[List[MotorTank]] = [MotorTank()]
tanks: Optional[List[MotorTank]] = None

# Solid motor parameters
grain_number: Optional[int] = 5
grain_density: Optional[float] = 1815
grain_outer_radius: Optional[float] = 0.033
grain_initial_inner_radius: Optional[float] = 0.015
grain_initial_height: Optional[float] = 0.12
grains_center_of_mass_position: Optional[float] = -0.85704
grain_separation: Optional[float] = 0.005
grain_number: Optional[int] = None
grain_density: Optional[float] = None
grain_outer_radius: Optional[float] = None
grain_initial_inner_radius: Optional[float] = None
grain_initial_height: Optional[float] = None
grains_center_of_mass_position: Optional[float] = None
grain_separation: Optional[float] = None

# Hybrid motor parameters
throat_radius: Optional[float] = 0.011
throat_radius: Optional[float] = None

# Optional parameters
interpolation_method: Optional[str] = "linear"
coordinate_system_orientation: Optional[CoordinateSystemOrientation] = (
interpolation_method: InterpolationMethods = InterpolationMethods.LINEAR
coordinate_system_orientation: CoordinateSystemOrientation = (
CoordinateSystemOrientation.NOZZLE_TO_COMBUSTION_CHAMBER
)
reshape_thrust_curve: Optional[bool] = False
reshape_thrust_curve: Union[bool, tuple] = False

# Computed parameters
_motor_kind: MotorKinds = PrivateAttr(default=MotorKinds.SOLID)
Expand Down
88 changes: 25 additions & 63 deletions lib/models/rocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
NoseCone,
Tail,
RailButtons,
FinsKinds,
)


Expand All @@ -17,71 +16,34 @@ class CoordinateSystemOrientation(str, Enum):


class Parachute(BaseModel):
name: str = "Main"
cd_s: float = 10
sampling_rate: int = 105
lag: float = 1.5
trigger: Union[str, float] = "apogee"
noise: Tuple[float, float, float] = (0, 8.3, 0.5)
name: str
cd_s: float
sampling_rate: int
lag: float
trigger: Union[str, float]
noise: Tuple[float, float, float]


class Rocket(BaseModel):
# Required parameters
motor: Motor = Motor()
radius: float = 0.0632
mass: float = 16.235
motor_position: float = -1.255
center_of_mass_without_motor: int = 0
inertia: Tuple[float, float, float] = (6.321, 6.321, 0.0346)
power_off_drag: List[Tuple[float, float]] = [
(0.0, 0.0),
(0.1, 0.1),
(0.2, 0.2),
]
power_on_drag: List[Tuple[float, float]] = [
(0.0, 0.0),
(0.1, 0.1),
(0.2, 0.2),
]

# Optional parameters
parachutes: Optional[List[Parachute]] = [Parachute()]
rail_buttons: Optional[RailButtons] = RailButtons(
name="RailButtons",
upper_button_position=-0.5,
lower_button_position=0.2,
angular_position=45,
)
nose: Optional[NoseCone] = NoseCone(
name="Nose",
length=0.55829,
kind="vonKarman",
position=1.278,
base_radius=0.0635,
rocket_radius=0.0635,
)
fins: Optional[List[Fins]] = [
Fins(
fins_kind=FinsKinds.TRAPEZOIDAL,
name="Fins",
n=4,
root_chord=0.12,
tip_chord=0.04,
span=0.1,
position=-1.04956,
cant_angle=0,
radius=0.0635,
airfoil=([(0.0, 0.0), (0.1, 0.1), (0.2, 0.2)], "RADIANS"),
)
]
tail: Optional[Tail] = Tail(
name="Tail",
top_radius=0.0635,
bottom_radius=0.0435,
length=0.06,
position=-1.194656,
radius=0.0635,
)
coordinate_system_orientation: Optional[CoordinateSystemOrientation] = (
motor: Motor
radius: float
mass: float
motor_position: float
center_of_mass_without_motor: int
inertia: Union[
Tuple[float, float, float],
Tuple[float, float, float, float, float, float],
] = (0, 0, 0)
power_off_drag: List[Tuple[float, float]] = [(0, 0)]
power_on_drag: List[Tuple[float, float]] = [(0, 0)]
coordinate_system_orientation: CoordinateSystemOrientation = (
CoordinateSystemOrientation.TAIL_TO_NOSE
)

# Optional parameters
parachutes: Optional[List[Parachute]] = None
rail_buttons: Optional[RailButtons] = None
nose: Optional[NoseCone] = None
fins: Optional[List[Fins]] = None
tail: Optional[Tail] = None
Loading
Loading