Skip to content

Commit 5927b63

Browse files
updates pydantic and fix optional parameters for the API
1 parent 0820715 commit 5927b63

File tree

13 files changed

+158
-161
lines changed

13 files changed

+158
-161
lines changed

lib/models/aerosurfaces.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ class Fins(BaseModel):
3434
name: str
3535
n: int
3636
root_chord: float
37-
tip_chord: Optional[float]
37+
tip_chord: Optional[float] = None
3838
span: float
3939
position: float
40-
cant_angle: float
41-
radius: float
42-
airfoil: Tuple[List[Tuple[float, float]], AngleUnit]
40+
cant_angle: Optional[float] = None
41+
radius: Optional[float] = None
42+
airfoil: Optional[Tuple[List[Tuple[float, float]], AngleUnit]] = None
4343

4444

4545
# TODO: implement airbrakes

lib/models/environment.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
import datetime
2+
from enum import Enum
23
from typing import Optional
34
from pydantic import BaseModel
45

56

7+
class AtmosphericModelTypes(str, Enum):
8+
STANDARD_ATMOSPHERE: str = "STANDARD_ATMOSPHERE"
9+
CUSTOM_ATMOSPHERE: str = "CUSTOM_ATMOSPHERE"
10+
WYOMING_SOUNDING: str = "WYOMING_SOUNDING"
11+
NOAARUCSOUNDING: str = "NOAARUCSOUNDING"
12+
FORECAST: str = "FORECAST"
13+
REANALYSIS: str = "REANALYSIS"
14+
ENSEMBLE: str = "ENSEMBLE"
15+
16+
617
class Env(BaseModel):
7-
latitude: float = 0
8-
longitude: float = 0
9-
elevation: Optional[int] = 1400
18+
latitude: float
19+
longitude: float
20+
elevation: Optional[int] = None
1021

11-
# Opional parameters
12-
atmospheric_model_type: Optional[str] = "standard_atmosphere"
13-
atmospheric_model_file: Optional[str] = "GFS"
22+
# Optional parameters
23+
atmospheric_model_type: Optional[AtmosphericModelTypes] = None
24+
atmospheric_model_file: Optional[str] = None
1425
date: Optional[datetime.datetime] = (
1526
datetime.datetime.today() + datetime.timedelta(days=1)
1627
)

lib/models/flight.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,24 @@
66

77

88
class EquationsOfMotion(str, Enum):
9-
STANDARD = "STANDARD"
10-
SOLID_PROPULSION = "SOLID_PROPULSION"
9+
STANDARD: str = "STANDARD"
10+
SOLID_PROPULSION: str = "SOLID_PROPULSION"
1111

1212

1313
class Flight(BaseModel):
1414
name: str = "Flight"
15-
environment: Env = Env()
16-
rocket: Rocket = Rocket()
17-
rail_length: float = 5.2
18-
inclination: Optional[int] = 80.0
19-
heading: Optional[int] = 90.0
15+
environment: Env
16+
rocket: Rocket
17+
rail_length: float
18+
inclination: Optional[int] = None
19+
heading: Optional[int] = None
2020
# TODO: implement initial_solution
21-
terminate_on_apogee: Optional[bool] = False
22-
max_time: Optional[int] = 600
23-
max_time_step: Optional[float] = 9999
24-
min_time_step: Optional[int] = 0
25-
rtol: Optional[float] = 1e-3
26-
atol: Optional[float] = 1e-3
27-
time_overshoot: Optional[bool] = True
28-
verbose: Optional[bool] = False
29-
equations_of_motion: Optional[EquationsOfMotion] = (
30-
EquationsOfMotion.STANDARD
31-
)
21+
terminate_on_apogee: Optional[bool] = None
22+
max_time: Optional[int] = None
23+
max_time_step: Optional[float] = None
24+
min_time_step: Optional[int] = None
25+
rtol: Optional[float] = None
26+
atol: Optional[float] = None
27+
time_overshoot: Optional[bool] = None
28+
verbose: Optional[bool] = None
29+
equations_of_motion: Optional[EquationsOfMotion] = None

lib/models/motor.py

Lines changed: 47 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from enum import Enum
2-
from typing import Optional, Tuple, List
2+
from typing import Optional, Tuple, List, Union
33
from pydantic import BaseModel, PrivateAttr
44

55

@@ -27,80 +27,81 @@ class TankFluids(BaseModel):
2727
density: float
2828

2929

30+
class InterpolationMethods(str, Enum):
31+
LINEAR: str = "LINEAR"
32+
SPLINE: str = "SPLINE"
33+
AKIMA: str = "AKIMA"
34+
35+
3036
class MotorTank(BaseModel):
3137
# Required parameters
32-
geometry: List[Tuple[Tuple[float, float], float]] = [
33-
((0.0, 5.0), 1.0),
34-
((5.0, 10.0), 2.0),
35-
]
36-
gas: TankFluids = TankFluids(name="GAS", density=100)
37-
liquid: TankFluids = TankFluids(name="LIQUID", density=1000)
38-
flux_time: Tuple[float, float] = (0.0, 3.9)
39-
position: float = 1.0
40-
discretize: int = 100
38+
geometry: List[Tuple[Tuple[float, float], float]]
39+
gas: TankFluids
40+
liquid: TankFluids
41+
flux_time: Tuple[float, float]
42+
position: float
43+
discretize: int
4144

4245
# Level based tank parameters
43-
liquid_height: Optional[float] = 0.5
46+
liquid_height: Optional[float]
4447

4548
# Mass based tank parameters
46-
liquid_mass: Optional[float] = 5.0
47-
gas_mass: Optional[float] = 0.1
49+
liquid_mass: Optional[float]
50+
gas_mass: Optional[float]
4851

4952
# Mass flow based tank parameters
50-
gas_mass_flow_rate_in: Optional[float] = 0.0
51-
gas_mass_flow_rate_out: Optional[float] = 0.1
52-
liquid_mass_flow_rate_in: Optional[float] = 0.0
53-
liquid_mass_flow_rate_out: Optional[float] = 1
54-
initial_liquid_mass: Optional[float] = 5.0
55-
initial_gas_mass: Optional[float] = 0.4
53+
gas_mass_flow_rate_in: Optional[float]
54+
gas_mass_flow_rate_out: Optional[float]
55+
liquid_mass_flow_rate_in: Optional[float]
56+
liquid_mass_flow_rate_out: Optional[float]
57+
initial_liquid_mass: Optional[float]
58+
initial_gas_mass: Optional[float]
5659

5760
# Ullage based tank parameters
58-
ullage: Optional[float] = 0.1
61+
ullage: Optional[float]
5962

6063
# Optional parameters
61-
name: Optional[str] = "Tank"
64+
name: Optional[str]
6265

6366
# Computed parameters
6467
tank_kind: TankKinds = TankKinds.MASS_FLOW
6568

6669

6770
class Motor(BaseModel):
6871
# Required parameters
69-
thrust_source: List[List[float]] = [[0.0, 0.0], [1.0, 1.0]]
70-
burn_time: float = 3.9
71-
nozzle_radius: float = 0.033
72-
dry_mass: float = 1.815
73-
dry_inertia: Tuple[float, float, float] = (0.125, 0.125, 0.002)
74-
center_of_dry_mass_position: float = 0.317
72+
thrust_source: List[List[float]]
73+
burn_time: float
74+
nozzle_radius: float
75+
dry_mass: float
76+
dry_inertia: Tuple[float, float, float]
77+
center_of_dry_mass_position: float
7578

7679
# Generic motor parameters
77-
chamber_radius: Optional[float] = 0.033
78-
chamber_height: Optional[float] = 0.1
79-
chamber_position: Optional[float] = 0.0
80-
propellant_initial_mass: Optional[float] = 1.0
81-
nozzle_position: Optional[float] = 0.0
80+
chamber_radius: Optional[float] = None
81+
chamber_height: Optional[float] = None
82+
chamber_position: Optional[float] = None
83+
propellant_initial_mass: Optional[float] = None
84+
nozzle_position: Optional[float] = None
8285

8386
# Liquid motor parameters
84-
tanks: Optional[List[MotorTank]] = [MotorTank()]
87+
tanks: Optional[List[MotorTank]] = None
8588

8689
# Solid motor parameters
87-
grain_number: Optional[int] = 5
88-
grain_density: Optional[float] = 1815
89-
grain_outer_radius: Optional[float] = 0.033
90-
grain_initial_inner_radius: Optional[float] = 0.015
91-
grain_initial_height: Optional[float] = 0.12
92-
grains_center_of_mass_position: Optional[float] = -0.85704
93-
grain_separation: Optional[float] = 0.005
90+
grain_number: Optional[int] = None
91+
grain_density: Optional[float] = None
92+
grain_outer_radius: Optional[float] = None
93+
grain_initial_inner_radius: Optional[float] = None
94+
grain_initial_height: Optional[float] = None
95+
grains_center_of_mass_position: Optional[float] = None
96+
grain_separation: Optional[float] = None
9497

9598
# Hybrid motor parameters
96-
throat_radius: Optional[float] = 0.011
99+
throat_radius: Optional[float] = None
97100

98101
# Optional parameters
99-
interpolation_method: Optional[str] = "linear"
100-
coordinate_system_orientation: Optional[CoordinateSystemOrientation] = (
101-
CoordinateSystemOrientation.NOZZLE_TO_COMBUSTION_CHAMBER
102-
)
103-
reshape_thrust_curve: Optional[bool] = False
102+
interpolation_method: Optional[InterpolationMethods] = None
103+
coordinate_system_orientation: Optional[CoordinateSystemOrientation] = None
104+
reshape_thrust_curve: Optional[Union[bool, tuple]] = None
104105

105106
# Computed parameters
106107
_motor_kind: MotorKinds = PrivateAttr(default=MotorKinds.SOLID)

lib/models/rocket.py

Lines changed: 20 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
NoseCone,
88
Tail,
99
RailButtons,
10-
FinsKinds,
1110
)
1211

1312

@@ -17,71 +16,29 @@ class CoordinateSystemOrientation(str, Enum):
1716

1817

1918
class Parachute(BaseModel):
20-
name: str = "Main"
21-
cd_s: float = 10
22-
sampling_rate: int = 105
23-
lag: float = 1.5
24-
trigger: Union[str, float] = "apogee"
25-
noise: Tuple[float, float, float] = (0, 8.3, 0.5)
19+
name: str
20+
cd_s: float
21+
sampling_rate: int
22+
lag: float
23+
trigger: Union[str, float]
24+
noise: Tuple[float, float, float]
2625

2726

2827
class Rocket(BaseModel):
2928
# Required parameters
30-
motor: Motor = Motor()
31-
radius: float = 0.0632
32-
mass: float = 16.235
33-
motor_position: float = -1.255
34-
center_of_mass_without_motor: int = 0
35-
inertia: Tuple[float, float, float] = (6.321, 6.321, 0.0346)
36-
power_off_drag: List[Tuple[float, float]] = [
37-
(0.0, 0.0),
38-
(0.1, 0.1),
39-
(0.2, 0.2),
40-
]
41-
power_on_drag: List[Tuple[float, float]] = [
42-
(0.0, 0.0),
43-
(0.1, 0.1),
44-
(0.2, 0.2),
45-
]
29+
motor: Motor
30+
radius: float
31+
mass: float
32+
motor_position: float
33+
center_of_mass_without_motor: int
34+
inertia: Tuple[float, float, float]
35+
power_off_drag: List[Tuple[float, float]]
36+
power_on_drag: List[Tuple[float, float]]
4637

4738
# Optional parameters
48-
parachutes: Optional[List[Parachute]] = [Parachute()]
49-
rail_buttons: Optional[RailButtons] = RailButtons(
50-
name="RailButtons",
51-
upper_button_position=-0.5,
52-
lower_button_position=0.2,
53-
angular_position=45,
54-
)
55-
nose: Optional[NoseCone] = NoseCone(
56-
name="Nose",
57-
length=0.55829,
58-
kind="vonKarman",
59-
position=1.278,
60-
base_radius=0.0635,
61-
rocket_radius=0.0635,
62-
)
63-
fins: Optional[List[Fins]] = [
64-
Fins(
65-
fins_kind=FinsKinds.TRAPEZOIDAL,
66-
name="Fins",
67-
n=4,
68-
root_chord=0.12,
69-
tip_chord=0.04,
70-
span=0.1,
71-
position=-1.04956,
72-
cant_angle=0,
73-
radius=0.0635,
74-
airfoil=([(0.0, 0.0), (0.1, 0.1), (0.2, 0.2)], "RADIANS"),
75-
)
76-
]
77-
tail: Optional[Tail] = Tail(
78-
name="Tail",
79-
top_radius=0.0635,
80-
bottom_radius=0.0435,
81-
length=0.06,
82-
position=-1.194656,
83-
radius=0.0635,
84-
)
85-
coordinate_system_orientation: Optional[CoordinateSystemOrientation] = (
86-
CoordinateSystemOrientation.TAIL_TO_NOSE
87-
)
39+
parachutes: Optional[List[Parachute]] = None
40+
rail_buttons: Optional[RailButtons] = None
41+
nose: Optional[NoseCone] = None
42+
fins: Optional[List[Fins]] = None
43+
tail: Optional[Tail] = None
44+
coordinate_system_orientation: Optional[CoordinateSystemOrientation] = None

lib/services/environment.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ def from_env_model(cls, env: Env) -> Self:
2929
date=env.date,
3030
)
3131
rocketpy_env.set_atmospheric_model(
32-
type=env.atmospheric_model_type, file=env.atmospheric_model_file
32+
type=env.atmospheric_model_type.value.lower(),
33+
file=env.atmospheric_model_file,
3334
)
3435
return cls(environment=rocketpy_env)
3536

lib/services/motor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ def from_motor_model(cls, motor: Motor) -> Self:
4646
if motor.coordinate_system_orientation
4747
else None
4848
),
49-
"interpolation_method": motor.interpolation_method,
50-
"reshape_thrust_curve": motor.reshape_thrust_curve,
49+
"interpolation_method": motor.interpolation_method.value.lower(),
50+
"reshape_thrust_curve": False or motor.reshape_thrust_curve,
5151
}
5252

5353
match motor.motor_kind:

lib/utils.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import io
44
import typing
55

6+
import numpy as np
7+
68
from starlette.datastructures import Headers, MutableHeaders
79
from starlette.types import ASGIApp, Message, Receive, Scope, Send
810

@@ -126,3 +128,16 @@ async def send_with_gzip(self, message: Message) -> None:
126128

127129
async def unattached_send(message: Message) -> typing.NoReturn:
128130
raise RuntimeError("send awaitable not set") # pragma: no cover
131+
132+
133+
def to_python_primitive(v):
134+
if hasattr(v, "source"):
135+
if isinstance(v.source, np.ndarray):
136+
return v.source.tolist()
137+
138+
if isinstance(v.source, (np.generic,)):
139+
return v.source.item()
140+
141+
return str(v.source)
142+
143+
return str(v)

0 commit comments

Comments
 (0)