rocketpy 1.6.0__tar.gz → 1.6.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rocketpy-1.6.0/rocketpy.egg-info → rocketpy-1.6.2}/PKG-INFO +11 -8
- {rocketpy-1.6.0 → rocketpy-1.6.2}/README.md +10 -7
- {rocketpy-1.6.0 → rocketpy-1.6.2}/pyproject.toml +10 -10
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/control/controller.py +2 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/environment/environment.py +15 -125
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/environment/fetchers.py +7 -4
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/mathutils/function.py +7 -7
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/mathutils/vector_matrix.py +8 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/motors/hybrid_motor.py +2 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/motors/liquid_motor.py +2 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/motors/motor.py +22 -1
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/motors/solid_motor.py +2 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/monte_carlo_plots.py +22 -7
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/hybrid_motor_prints.py +1 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/liquid_motor_prints.py +1 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/motor_prints.py +1 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/rocket_prints.py +1 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/solid_motor_prints.py +1 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/rocket.py +48 -17
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/sensors/accelerometer.py +4 -1
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/sensors/barometer.py +1 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/sensors/gnss_receiver.py +1 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/sensors/gyroscope.py +3 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/sensors/sensor.py +4 -3
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/simulation/monte_carlo.py +66 -26
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/tools.py +152 -147
- {rocketpy-1.6.0 → rocketpy-1.6.2/rocketpy.egg-info}/PKG-INFO +11 -8
- {rocketpy-1.6.0 → rocketpy-1.6.2}/LICENSE +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/requirements.txt +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/_encoders.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/control/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/environment/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/environment/environment_analysis.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/environment/tools.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/environment/weather_model_mapping.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/mathutils/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/motors/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/motors/fluid.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/motors/tank.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/motors/tank_geometry.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/aero_surface_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/compare/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/compare/compare.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/compare/compare_flights.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/environment_analysis_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/environment_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/flight_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/fluid_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/hybrid_motor_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/liquid_motor_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/motor_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/rocket_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/sensitivity_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/solid_motor_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/tank_geometry_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/plots/tank_plots.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/aero_surface_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/compare_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/controller_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/environment_analysis_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/environment_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/flight_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/fluid_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/monte_carlo_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/parachute_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/sensitivity_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/sensors_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/tank_geometry_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/prints/tank_prints.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/aero_surface.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/air_brakes.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/fins/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/fins/elliptical_fins.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/fins/fins.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/fins/free_form_fins.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/fins/trapezoidal_fins.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/generic_surface.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/linear_generic_surface.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/nose_cone.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/rail_buttons.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/aero_surface/tail.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/components.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/rocket/parachute.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/sensitivity/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/sensitivity/sensitivity_model.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/sensors/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/simulation/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/simulation/flight.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/simulation/flight_data_importer.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/stochastic/__init__.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/stochastic/stochastic_aero_surfaces.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/stochastic/stochastic_environment.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/stochastic/stochastic_flight.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/stochastic/stochastic_generic_motor.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/stochastic/stochastic_model.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/stochastic/stochastic_motor_model.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/stochastic/stochastic_parachute.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/stochastic/stochastic_rocket.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/stochastic/stochastic_solid_motor.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/units.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy/utilities.py +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy.egg-info/SOURCES.txt +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy.egg-info/dependency_links.txt +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy.egg-info/requires.txt +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/rocketpy.egg-info/top_level.txt +0 -0
- {rocketpy-1.6.0 → rocketpy-1.6.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: rocketpy
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.2
|
|
4
4
|
Summary: Advanced 6-DOF trajectory simulation for High-Power Rocketry.
|
|
5
5
|
Author-email: Giovani Hidalgo Ceotto <ghceotto@gmail.com>
|
|
6
6
|
Project-URL: homepage, https://rocketpy.org/
|
|
@@ -52,18 +52,18 @@ Requires-Dist: rocketpy[monte-carlo]; extra == "all"
|
|
|
52
52
|
<br>
|
|
53
53
|
|
|
54
54
|
[](https://colab.research.google.com/github/RocketPy-Team/rocketpy/blob/master/docs/notebooks/getting_started_colab.ipynb)
|
|
55
|
-
[](https://pypi.org/project/rocketpy/)
|
|
56
55
|
[](https://docs.rocketpy.org/en/latest/?badge=latest)
|
|
56
|
+
[](https://pypi.org/project/rocketpy/)
|
|
57
|
+

|
|
57
58
|
[](https://codecov.io/gh/RocketPy-Team/RocketPy)
|
|
59
|
+
[](https://github.com/psf/black)
|
|
58
60
|
[](https://github.com/RocketPy-Team/RocketPy/graphs/contributors)
|
|
59
|
-
[](https://discord.gg/b6xYnNh)
|
|
60
61
|
[](https://github.com/sponsors/RocketPy-Team)
|
|
62
|
+
[](https://discord.gg/b6xYnNh)
|
|
61
63
|
[](https://www.instagram.com/rocketpyteam)
|
|
62
64
|
[](https://www.linkedin.com/company/rocketpy)
|
|
63
65
|
[](http://dx.doi.org/10.1061/%28ASCE%29AS.1943-5525.0001331)
|
|
64
66
|
|
|
65
|
-
<br>
|
|
66
|
-
|
|
67
67
|
# RocketPy
|
|
68
68
|
|
|
69
69
|
RocketPy is the next-generation trajectory simulation solution for High-Power Rocketry. The code is written as a [Python](http://www.python.org) library and allows for a complete 6 degrees of freedom simulation of a rocket's flight trajectory, including high-fidelity variable mass effects as well as descent under parachutes. Weather conditions, such as wind profiles, can be imported from sophisticated datasets, allowing for realistic scenarios. Furthermore, the implementation facilitates complex simulations, such as multi-stage rockets, design and trajectory optimization and dispersion analysis.
|
|
@@ -78,7 +78,7 @@ RocketPy is the next-generation trajectory simulation solution for High-Power Ro
|
|
|
78
78
|
|
|
79
79
|
2. **Accurate Weather Modeling**
|
|
80
80
|
- Supports International Standard Atmosphere (1976)
|
|
81
|
-
- Custom atmospheric profiles and Soundings (Wyoming
|
|
81
|
+
- Custom atmospheric profiles and Soundings (Wyoming)
|
|
82
82
|
- Weather forecasts, reanalysis, and ensembles for realistic scenarios
|
|
83
83
|
|
|
84
84
|
3. **Aerodynamic Models**
|
|
@@ -125,6 +125,9 @@ Flight data and rocket parameters used in this comparison were kindly provided b
|
|
|
125
125
|
| NDRT launch vehicle | Apogee time (s) | 16.77 | 17.10 | **-1.90 %** |
|
|
126
126
|
| NDRT launch vehicle | Maximum velocity (m/s) | 172.86 | 168.95 | **2.31 %** |
|
|
127
127
|
|
|
128
|
+
Over years of development and testing, RocketPy has been validated across an expanding range of flight scenarios.
|
|
129
|
+
For more information on these validated flights, visit our [Flight Examples](https://docs.rocketpy.org/en/latest/examples/index.html) page in the documentation.
|
|
130
|
+
|
|
128
131
|
# Documentation
|
|
129
132
|
|
|
130
133
|
Check out documentation details using the links below:
|
|
@@ -206,7 +209,7 @@ env = Environment(
|
|
|
206
209
|
latitude=32.990254,
|
|
207
210
|
longitude=-106.974998,
|
|
208
211
|
elevation=1400,
|
|
209
|
-
)
|
|
212
|
+
)
|
|
210
213
|
|
|
211
214
|
tomorrow = datetime.date.today() + datetime.timedelta(days=1)
|
|
212
215
|
|
|
@@ -397,7 +400,7 @@ You can also become a [sponsor](https://github.com/sponsors/RocketPy-Team) and h
|
|
|
397
400
|
|
|
398
401
|
If you are actively using RocketPy in one of your projects, reaching out to our core team via [Discord](https://discord.gg/b6xYnNh) and providing feedback can help improve RocketPy a lot!
|
|
399
402
|
|
|
400
|
-
And if you are interested in going one step further, please read [
|
|
403
|
+
And if you are interested in going one step further, please read the [development documentation](https://docs.rocketpy.org/en/latest/development/index.html) to learn more about how you can contribute to the development of this next-gen trajectory simulation solution for rocketry.
|
|
401
404
|
|
|
402
405
|
## License
|
|
403
406
|
|
|
@@ -7,18 +7,18 @@
|
|
|
7
7
|
<br>
|
|
8
8
|
|
|
9
9
|
[](https://colab.research.google.com/github/RocketPy-Team/rocketpy/blob/master/docs/notebooks/getting_started_colab.ipynb)
|
|
10
|
-
[](https://pypi.org/project/rocketpy/)
|
|
11
10
|
[](https://docs.rocketpy.org/en/latest/?badge=latest)
|
|
11
|
+
[](https://pypi.org/project/rocketpy/)
|
|
12
|
+

|
|
12
13
|
[](https://codecov.io/gh/RocketPy-Team/RocketPy)
|
|
14
|
+
[](https://github.com/psf/black)
|
|
13
15
|
[](https://github.com/RocketPy-Team/RocketPy/graphs/contributors)
|
|
14
|
-
[](https://discord.gg/b6xYnNh)
|
|
15
16
|
[](https://github.com/sponsors/RocketPy-Team)
|
|
17
|
+
[](https://discord.gg/b6xYnNh)
|
|
16
18
|
[](https://www.instagram.com/rocketpyteam)
|
|
17
19
|
[](https://www.linkedin.com/company/rocketpy)
|
|
18
20
|
[](http://dx.doi.org/10.1061/%28ASCE%29AS.1943-5525.0001331)
|
|
19
21
|
|
|
20
|
-
<br>
|
|
21
|
-
|
|
22
22
|
# RocketPy
|
|
23
23
|
|
|
24
24
|
RocketPy is the next-generation trajectory simulation solution for High-Power Rocketry. The code is written as a [Python](http://www.python.org) library and allows for a complete 6 degrees of freedom simulation of a rocket's flight trajectory, including high-fidelity variable mass effects as well as descent under parachutes. Weather conditions, such as wind profiles, can be imported from sophisticated datasets, allowing for realistic scenarios. Furthermore, the implementation facilitates complex simulations, such as multi-stage rockets, design and trajectory optimization and dispersion analysis.
|
|
@@ -33,7 +33,7 @@ RocketPy is the next-generation trajectory simulation solution for High-Power Ro
|
|
|
33
33
|
|
|
34
34
|
2. **Accurate Weather Modeling**
|
|
35
35
|
- Supports International Standard Atmosphere (1976)
|
|
36
|
-
- Custom atmospheric profiles and Soundings (Wyoming
|
|
36
|
+
- Custom atmospheric profiles and Soundings (Wyoming)
|
|
37
37
|
- Weather forecasts, reanalysis, and ensembles for realistic scenarios
|
|
38
38
|
|
|
39
39
|
3. **Aerodynamic Models**
|
|
@@ -80,6 +80,9 @@ Flight data and rocket parameters used in this comparison were kindly provided b
|
|
|
80
80
|
| NDRT launch vehicle | Apogee time (s) | 16.77 | 17.10 | **-1.90 %** |
|
|
81
81
|
| NDRT launch vehicle | Maximum velocity (m/s) | 172.86 | 168.95 | **2.31 %** |
|
|
82
82
|
|
|
83
|
+
Over years of development and testing, RocketPy has been validated across an expanding range of flight scenarios.
|
|
84
|
+
For more information on these validated flights, visit our [Flight Examples](https://docs.rocketpy.org/en/latest/examples/index.html) page in the documentation.
|
|
85
|
+
|
|
83
86
|
# Documentation
|
|
84
87
|
|
|
85
88
|
Check out documentation details using the links below:
|
|
@@ -161,7 +164,7 @@ env = Environment(
|
|
|
161
164
|
latitude=32.990254,
|
|
162
165
|
longitude=-106.974998,
|
|
163
166
|
elevation=1400,
|
|
164
|
-
)
|
|
167
|
+
)
|
|
165
168
|
|
|
166
169
|
tomorrow = datetime.date.today() + datetime.timedelta(days=1)
|
|
167
170
|
|
|
@@ -352,7 +355,7 @@ You can also become a [sponsor](https://github.com/sponsors/RocketPy-Team) and h
|
|
|
352
355
|
|
|
353
356
|
If you are actively using RocketPy in one of your projects, reaching out to our core team via [Discord](https://discord.gg/b6xYnNh) and providing feedback can help improve RocketPy a lot!
|
|
354
357
|
|
|
355
|
-
And if you are interested in going one step further, please read [
|
|
358
|
+
And if you are interested in going one step further, please read the [development documentation](https://docs.rocketpy.org/en/latest/development/index.html) to learn more about how you can contribute to the development of this next-gen trajectory simulation solution for rocketry.
|
|
356
359
|
|
|
357
360
|
## License
|
|
358
361
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "rocketpy"
|
|
3
|
-
version = "1.6.
|
|
3
|
+
version = "1.6.2"
|
|
4
4
|
description="Advanced 6-DOF trajectory simulation for High-Power Rocketry."
|
|
5
5
|
dynamic = ["dependencies"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -30,8 +30,8 @@ packages = { find = { where = ["."], include = ["rocketpy*"] } }
|
|
|
30
30
|
dependencies = { file = ["requirements.txt"] }
|
|
31
31
|
|
|
32
32
|
[project.optional-dependencies]
|
|
33
|
-
tests = [
|
|
34
|
-
"pytest",
|
|
33
|
+
tests = [
|
|
34
|
+
"pytest",
|
|
35
35
|
"pytest-coverage",
|
|
36
36
|
"black[jupyter]",
|
|
37
37
|
"flake8-black",
|
|
@@ -42,12 +42,12 @@ tests = [
|
|
|
42
42
|
"isort"
|
|
43
43
|
]
|
|
44
44
|
|
|
45
|
-
env-analysis = [
|
|
46
|
-
"windrose>=1.6.8",
|
|
47
|
-
"timezonefinder",
|
|
48
|
-
"jsonpickle",
|
|
49
|
-
"ipython",
|
|
50
|
-
"ipywidgets>=7.6.3"
|
|
45
|
+
env-analysis = [
|
|
46
|
+
"windrose>=1.6.8",
|
|
47
|
+
"timezonefinder",
|
|
48
|
+
"jsonpickle",
|
|
49
|
+
"ipython",
|
|
50
|
+
"ipywidgets>=7.6.3"
|
|
51
51
|
]
|
|
52
52
|
|
|
53
53
|
monte-carlo = [
|
|
@@ -59,7 +59,7 @@ monte-carlo = [
|
|
|
59
59
|
all = ["rocketpy[env-analysis]", "rocketpy[monte-carlo]"]
|
|
60
60
|
|
|
61
61
|
[tool.black]
|
|
62
|
-
line-length = 88
|
|
62
|
+
line-length = 88
|
|
63
63
|
include = '\.py$|\.ipynb$'
|
|
64
64
|
skip-string-normalization = true
|
|
65
65
|
|
|
@@ -84,8 +84,10 @@ class _Controller:
|
|
|
84
84
|
None
|
|
85
85
|
"""
|
|
86
86
|
self.interactive_objects = interactive_objects
|
|
87
|
+
self.base_controller_function = controller_function
|
|
87
88
|
self.controller_function = self.__init_controller_function(controller_function)
|
|
88
89
|
self.sampling_rate = sampling_rate
|
|
90
|
+
self.initial_observed_variables = initial_observed_variables
|
|
89
91
|
self.name = name
|
|
90
92
|
self.prints = _ControllerPrints(self)
|
|
91
93
|
|
|
@@ -16,7 +16,6 @@ from rocketpy.environment.fetchers import (
|
|
|
16
16
|
fetch_gfs_file_return_dataset,
|
|
17
17
|
fetch_hiresw_file_return_dataset,
|
|
18
18
|
fetch_nam_file_return_dataset,
|
|
19
|
-
fetch_noaaruc_sounding,
|
|
20
19
|
fetch_open_elevation,
|
|
21
20
|
fetch_rap_file_return_dataset,
|
|
22
21
|
fetch_wyoming_sounding,
|
|
@@ -142,11 +141,11 @@ class Environment:
|
|
|
142
141
|
Environment.atmospheric_model_type : string
|
|
143
142
|
Describes the atmospheric model which is being used. Can only assume the
|
|
144
143
|
following values: ``standard_atmosphere``, ``custom_atmosphere``,
|
|
145
|
-
``wyoming_sounding``, ``
|
|
144
|
+
``wyoming_sounding``, ``Forecast``, ``Reanalysis``,
|
|
146
145
|
``Ensemble``.
|
|
147
146
|
Environment.atmospheric_model_file : string
|
|
148
147
|
Address of the file used for the atmospheric model being used. Only
|
|
149
|
-
defined for ``wyoming_sounding``, ``
|
|
148
|
+
defined for ``wyoming_sounding``, ``Forecast``,
|
|
150
149
|
``Reanalysis``, ``Ensemble``
|
|
151
150
|
Environment.atmospheric_model_dict : dictionary
|
|
152
151
|
Dictionary used to properly interpret ``netCDF`` and ``OPeNDAP`` files.
|
|
@@ -1053,24 +1052,6 @@ class Environment:
|
|
|
1053
1052
|
|
|
1054
1053
|
.. _weather.uwyo: http://weather.uwyo.edu/upperair/sounding.html
|
|
1055
1054
|
|
|
1056
|
-
- ``NOAARucSounding``: sets pressure, temperature, wind-u
|
|
1057
|
-
and wind-v profiles and surface elevation obtained from
|
|
1058
|
-
an upper air sounding given by the file parameter through
|
|
1059
|
-
an URL. This URL should point to a data webpage obtained
|
|
1060
|
-
through NOAA's Ruc Sounding servers, which can be accessed
|
|
1061
|
-
in `rucsoundings`_. Selecting ROABs as the
|
|
1062
|
-
initial data source, specifying the station through it's
|
|
1063
|
-
WMO-ID and opting for the ASCII (GSD format) button, the
|
|
1064
|
-
following example URL opens up:
|
|
1065
|
-
|
|
1066
|
-
https://rucsoundings.noaa.gov/get_raobs.cgi?data_source=RAOB&latest=latest&start_year=2019&start_month_name=Feb&start_mday=5&start_hour=12&start_min=0&n_hrs=1.0&fcst_len=shortest&airport=83779&text=Ascii%20text%20%28GSD%20format%29&hydrometeors=false&start=latest
|
|
1067
|
-
|
|
1068
|
-
Any ASCII GSD format page from this server can be read,
|
|
1069
|
-
so information from virtual soundings such as GFS and NAM
|
|
1070
|
-
can also be imported.
|
|
1071
|
-
|
|
1072
|
-
.. _rucsoundings: https://rucsoundings.noaa.gov/
|
|
1073
|
-
|
|
1074
1055
|
- ``windy_atmosphere``: sets pressure, temperature, wind-u and
|
|
1075
1056
|
wind-v profiles and surface elevation obtained from the Windy API.
|
|
1076
1057
|
See file argument to specify the model as either ``ECMWF``,
|
|
@@ -1279,8 +1260,6 @@ class Environment:
|
|
|
1279
1260
|
self.process_standard_atmosphere()
|
|
1280
1261
|
elif type == "wyoming_sounding":
|
|
1281
1262
|
self.process_wyoming_sounding(file)
|
|
1282
|
-
elif type == "noaarucsounding":
|
|
1283
|
-
self.process_noaaruc_sounding(file)
|
|
1284
1263
|
elif type == "custom_atmosphere":
|
|
1285
1264
|
self.process_custom_atmosphere(pressure, temperature, wind_u, wind_v)
|
|
1286
1265
|
elif type == "windy":
|
|
@@ -1334,7 +1313,7 @@ class Environment:
|
|
|
1334
1313
|
self.__set_wind_speed_function(0)
|
|
1335
1314
|
|
|
1336
1315
|
# 80k meters is the limit of the standard atmosphere
|
|
1337
|
-
self.
|
|
1316
|
+
self._max_expected_height = 80000
|
|
1338
1317
|
|
|
1339
1318
|
def process_custom_atmosphere(
|
|
1340
1319
|
self, pressure=None, temperature=None, wind_u=0, wind_v=0
|
|
@@ -1411,7 +1390,7 @@ class Environment:
|
|
|
1411
1390
|
None
|
|
1412
1391
|
"""
|
|
1413
1392
|
# Initialize an estimate of the maximum expected atmospheric model height
|
|
1414
|
-
max_expected_height = 1000
|
|
1393
|
+
max_expected_height = self.max_expected_height or 1000
|
|
1415
1394
|
|
|
1416
1395
|
# Save pressure profile
|
|
1417
1396
|
if pressure is None:
|
|
@@ -1455,7 +1434,7 @@ class Environment:
|
|
|
1455
1434
|
self.__reset_wind_direction_function()
|
|
1456
1435
|
self.__reset_wind_speed_function()
|
|
1457
1436
|
|
|
1458
|
-
self.
|
|
1437
|
+
self._max_expected_height = max_expected_height
|
|
1459
1438
|
|
|
1460
1439
|
def process_windy_atmosphere(
|
|
1461
1440
|
self, model="ECMWF"
|
|
@@ -1530,7 +1509,7 @@ class Environment:
|
|
|
1530
1509
|
self.__set_wind_speed_function(data_array[:, (1, 7)])
|
|
1531
1510
|
|
|
1532
1511
|
# Save maximum expected height
|
|
1533
|
-
self.
|
|
1512
|
+
self._max_expected_height = max(altitude_array[0], altitude_array[-1])
|
|
1534
1513
|
|
|
1535
1514
|
# Get elevation data from file
|
|
1536
1515
|
self.elevation = float(response["header"]["elevation"])
|
|
@@ -1668,7 +1647,7 @@ class Environment:
|
|
|
1668
1647
|
)
|
|
1669
1648
|
|
|
1670
1649
|
# Save maximum expected height
|
|
1671
|
-
self.
|
|
1650
|
+
self._max_expected_height = data_array[-1, 1]
|
|
1672
1651
|
|
|
1673
1652
|
def process_noaaruc_sounding(self, file): # pylint: disable=too-many-statements
|
|
1674
1653
|
"""Import and process the upper air sounding data from `NOAA
|
|
@@ -1689,107 +1668,18 @@ class Environment:
|
|
|
1689
1668
|
|
|
1690
1669
|
See also
|
|
1691
1670
|
--------
|
|
1692
|
-
|
|
1671
|
+
This method is deprecated and will be fully deleted in version 1.8.0.
|
|
1693
1672
|
|
|
1694
1673
|
Returns
|
|
1695
1674
|
-------
|
|
1696
1675
|
None
|
|
1697
1676
|
"""
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
lines = response.text.split("\n")
|
|
1703
|
-
|
|
1704
|
-
# Process GSD format (https://rucsoundings.noaa.gov/raob_format.html)
|
|
1705
|
-
|
|
1706
|
-
# Extract elevation data
|
|
1707
|
-
for line in lines:
|
|
1708
|
-
# Split line into columns
|
|
1709
|
-
columns = re.split(" +", line)[1:]
|
|
1710
|
-
if len(columns) > 0:
|
|
1711
|
-
if columns[0] == "1" and columns[5] != "99999":
|
|
1712
|
-
# Save elevation
|
|
1713
|
-
self.elevation = float(columns[5])
|
|
1714
|
-
else:
|
|
1715
|
-
# No elevation data available
|
|
1716
|
-
pass
|
|
1717
|
-
|
|
1718
|
-
pressure_array = []
|
|
1719
|
-
barometric_height_array = []
|
|
1720
|
-
temperature_array = []
|
|
1721
|
-
wind_speed_array = []
|
|
1722
|
-
wind_direction_array = []
|
|
1723
|
-
|
|
1724
|
-
for line in lines:
|
|
1725
|
-
# Split line into columns
|
|
1726
|
-
columns = re.split(" +", line)[1:]
|
|
1727
|
-
if len(columns) < 6:
|
|
1728
|
-
# skip lines with less than 6 columns
|
|
1729
|
-
continue
|
|
1730
|
-
if columns[0] in ["4", "5", "6", "7", "8", "9"]:
|
|
1731
|
-
# Convert columns to floats
|
|
1732
|
-
columns = np.array(columns, dtype=float)
|
|
1733
|
-
# Select relevant columns
|
|
1734
|
-
altitude, pressure, temperature, wind_direction, wind_speed = columns[
|
|
1735
|
-
[2, 1, 3, 5, 6]
|
|
1736
|
-
]
|
|
1737
|
-
# Check for missing values
|
|
1738
|
-
if altitude == 99999:
|
|
1739
|
-
continue
|
|
1740
|
-
# Save values only if they are not missing
|
|
1741
|
-
if pressure != 99999:
|
|
1742
|
-
pressure_array.append([altitude, pressure])
|
|
1743
|
-
barometric_height_array.append([pressure, altitude])
|
|
1744
|
-
if temperature != 99999:
|
|
1745
|
-
temperature_array.append([altitude, temperature])
|
|
1746
|
-
if wind_direction != 99999:
|
|
1747
|
-
wind_direction_array.append([altitude, wind_direction])
|
|
1748
|
-
if wind_speed != 99999:
|
|
1749
|
-
wind_speed_array.append([altitude, wind_speed])
|
|
1750
|
-
|
|
1751
|
-
# Convert lists to arrays
|
|
1752
|
-
pressure_array = np.array(pressure_array)
|
|
1753
|
-
barometric_height_array = np.array(barometric_height_array)
|
|
1754
|
-
temperature_array = np.array(temperature_array)
|
|
1755
|
-
wind_speed_array = np.array(wind_speed_array)
|
|
1756
|
-
wind_direction_array = np.array(wind_direction_array)
|
|
1757
|
-
|
|
1758
|
-
# Converts 10*hPa to Pa and save values
|
|
1759
|
-
pressure_array[:, 1] = 10 * pressure_array[:, 1]
|
|
1760
|
-
self.__set_pressure_function(pressure_array)
|
|
1761
|
-
# Converts 10*hPa to Pa and save values
|
|
1762
|
-
barometric_height_array[:, 0] = 10 * barometric_height_array[:, 0]
|
|
1763
|
-
self.__set_barometric_height_function(barometric_height_array)
|
|
1764
|
-
|
|
1765
|
-
# Convert C to K and save values
|
|
1766
|
-
temperature_array[:, 1] = temperature_array[:, 1] / 10 + 273.15
|
|
1767
|
-
self.__set_temperature_function(temperature_array)
|
|
1768
|
-
|
|
1769
|
-
# Process wind-u and wind-v
|
|
1770
|
-
# Converts Knots to m/s
|
|
1771
|
-
wind_speed_array[:, 1] = wind_speed_array[:, 1] * 1.852 / 3.6
|
|
1772
|
-
wind_heading_array = wind_direction_array[:, :] * 1
|
|
1773
|
-
# Convert wind direction to wind heading
|
|
1774
|
-
wind_heading_array[:, 1] = (wind_direction_array[:, 1] + 180) % 360
|
|
1775
|
-
wind_u = wind_speed_array[:, :] * 1
|
|
1776
|
-
wind_v = wind_speed_array[:, :] * 1
|
|
1777
|
-
wind_u[:, 1] = wind_speed_array[:, 1] * np.sin(
|
|
1778
|
-
np.deg2rad(wind_heading_array[:, 1])
|
|
1779
|
-
)
|
|
1780
|
-
wind_v[:, 1] = wind_speed_array[:, 1] * np.cos(
|
|
1781
|
-
np.deg2rad(wind_heading_array[:, 1])
|
|
1677
|
+
warnings.warn(
|
|
1678
|
+
"NOAA RUC models are no longer available. "
|
|
1679
|
+
"This method is deprecated and will be fully deleted in version 1.8.0.",
|
|
1680
|
+
DeprecationWarning,
|
|
1782
1681
|
)
|
|
1783
|
-
|
|
1784
|
-
# Save wind data
|
|
1785
|
-
self.__set_wind_direction_function(wind_direction_array)
|
|
1786
|
-
self.__set_wind_heading_function(wind_heading_array)
|
|
1787
|
-
self.__set_wind_speed_function(wind_speed_array)
|
|
1788
|
-
self.__set_wind_velocity_x_function(wind_u)
|
|
1789
|
-
self.__set_wind_velocity_y_function(wind_v)
|
|
1790
|
-
|
|
1791
|
-
# Save maximum expected height
|
|
1792
|
-
self.max_expected_height = pressure_array[-1, 0]
|
|
1682
|
+
return file
|
|
1793
1683
|
|
|
1794
1684
|
def process_forecast_reanalysis(
|
|
1795
1685
|
self, file, dictionary
|
|
@@ -2009,7 +1899,7 @@ class Environment:
|
|
|
2009
1899
|
self.__set_wind_speed_function(data_array[:, (1, 7)])
|
|
2010
1900
|
|
|
2011
1901
|
# Save maximum expected height
|
|
2012
|
-
self.
|
|
1902
|
+
self._max_expected_height = max(height[0], height[-1])
|
|
2013
1903
|
|
|
2014
1904
|
# Get elevation data from file
|
|
2015
1905
|
if dictionary["surface_geopotential_height"] is not None:
|
|
@@ -2354,7 +2244,7 @@ class Environment:
|
|
|
2354
2244
|
self.__set_wind_speed_function(data_array[:, (1, 7)])
|
|
2355
2245
|
|
|
2356
2246
|
# Save other attributes
|
|
2357
|
-
self.
|
|
2247
|
+
self._max_expected_height = max(height[0], height[-1])
|
|
2358
2248
|
self.ensemble_member = member
|
|
2359
2249
|
|
|
2360
2250
|
# Update air density, speed of sound and dynamic viscosity
|
|
@@ -5,6 +5,7 @@ functions may be changed without notice in future feature releases.
|
|
|
5
5
|
|
|
6
6
|
import re
|
|
7
7
|
import time
|
|
8
|
+
import warnings
|
|
8
9
|
from datetime import datetime, timedelta, timezone
|
|
9
10
|
|
|
10
11
|
import netCDF4
|
|
@@ -347,10 +348,12 @@ def fetch_noaaruc_sounding(file):
|
|
|
347
348
|
ImportError
|
|
348
349
|
If unable to load the specified file or the file content is too short.
|
|
349
350
|
"""
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
351
|
+
warnings.warn(
|
|
352
|
+
"The NOAA RUC soundings are deprecated since September 30th, 2024. "
|
|
353
|
+
"This method will be removed in version 1.8.0.",
|
|
354
|
+
DeprecationWarning,
|
|
355
|
+
)
|
|
356
|
+
return file
|
|
354
357
|
|
|
355
358
|
|
|
356
359
|
@exponential_backoff(max_attempts=5, base_delay=2, max_delay=60)
|
|
@@ -3171,7 +3171,7 @@ class Function: # pylint: disable=too-many-public-methods
|
|
|
3171
3171
|
)
|
|
3172
3172
|
# Generate the data points using the callable
|
|
3173
3173
|
x = np.linspace(lower, upper, samples)
|
|
3174
|
-
data_points = np.column_stack((x, self
|
|
3174
|
+
data_points = np.column_stack((x, self(x)))
|
|
3175
3175
|
else:
|
|
3176
3176
|
# If the source is already an array, use it as is
|
|
3177
3177
|
data_points = self.source
|
|
@@ -3247,12 +3247,12 @@ class Function: # pylint: disable=too-many-public-methods
|
|
|
3247
3247
|
)
|
|
3248
3248
|
|
|
3249
3249
|
source_len, source_dim = source.shape
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3250
|
+
if not source_len == 1: # do not check for one point Functions
|
|
3251
|
+
if source_len < source_dim:
|
|
3252
|
+
raise ValueError(
|
|
3253
|
+
"Too few data points to define a domain. The number of rows "
|
|
3254
|
+
"must be greater than or equal to the number of columns."
|
|
3255
|
+
)
|
|
3256
3256
|
|
|
3257
3257
|
return source
|
|
3258
3258
|
|
|
@@ -418,6 +418,10 @@ class Vector:
|
|
|
418
418
|
"""Returns the k vector, [0, 0, 1]."""
|
|
419
419
|
return Vector([0, 0, 1])
|
|
420
420
|
|
|
421
|
+
def to_dict(self):
|
|
422
|
+
"""Returns the vector as a JSON compatible element."""
|
|
423
|
+
return list(self.components)
|
|
424
|
+
|
|
421
425
|
|
|
422
426
|
class Matrix:
|
|
423
427
|
"""Pure Python 3x3 Matrix class for simple matrix-matrix and matrix-vector
|
|
@@ -998,6 +1002,10 @@ class Matrix:
|
|
|
998
1002
|
+ f" [{self.zx}, {self.zy}, {self.zz}])"
|
|
999
1003
|
)
|
|
1000
1004
|
|
|
1005
|
+
def to_dict(self):
|
|
1006
|
+
"""Returns the matrix as a JSON compatible element."""
|
|
1007
|
+
return [list(row) for row in self.components]
|
|
1008
|
+
|
|
1001
1009
|
@staticmethod
|
|
1002
1010
|
def identity():
|
|
1003
1011
|
"""Returns the 3x3 identity matrix."""
|
|
@@ -72,6 +72,8 @@ class HybridMotor(Motor):
|
|
|
72
72
|
HybridMotor.propellant_mass : Function
|
|
73
73
|
Total propellant mass in kg as a function of time, this includes the
|
|
74
74
|
mass of fluids in each tank and the mass of the solid grains.
|
|
75
|
+
HybridMotor.structural_mass_ratio: float
|
|
76
|
+
Initial ratio between the dry mass and the total mass.
|
|
75
77
|
HybridMotor.total_mass_flow_rate : Function
|
|
76
78
|
Time derivative of propellant total mass in kg/s as a function
|
|
77
79
|
of time as obtained by the thrust source.
|
|
@@ -47,6 +47,8 @@ class LiquidMotor(Motor):
|
|
|
47
47
|
LiquidMotor.propellant_mass : Function
|
|
48
48
|
Total propellant mass in kg as a function of time, includes fuel
|
|
49
49
|
and oxidizer.
|
|
50
|
+
LiquidMotor.structural_mass_ratio: float
|
|
51
|
+
Initial ratio between the dry mass and the total mass.
|
|
50
52
|
LiquidMotor.total_mass_flow_rate : Function
|
|
51
53
|
Time derivative of propellant total mass in kg/s as a function
|
|
52
54
|
of time as obtained by the tanks mass flow.
|
|
@@ -49,6 +49,8 @@ class Motor(ABC):
|
|
|
49
49
|
Motor.propellant_mass : Function
|
|
50
50
|
Total propellant mass in kg as a function of time, including solid,
|
|
51
51
|
liquid and gas phases.
|
|
52
|
+
Motor.structural_mass_ratio: float
|
|
53
|
+
Initial ratio between the dry mass and the total mass.
|
|
52
54
|
Motor.total_mass_flow_rate : Function
|
|
53
55
|
Time derivative of propellant total mass in kg/s as a function
|
|
54
56
|
of time as obtained by the thrust source.
|
|
@@ -370,7 +372,7 @@ class Motor(ABC):
|
|
|
370
372
|
dry_mass : float
|
|
371
373
|
Motor dry mass in kg.
|
|
372
374
|
"""
|
|
373
|
-
if dry_mass:
|
|
375
|
+
if dry_mass is not None:
|
|
374
376
|
if isinstance(dry_mass, (int, float)):
|
|
375
377
|
self._dry_mass = dry_mass
|
|
376
378
|
else:
|
|
@@ -497,6 +499,24 @@ class Motor(ABC):
|
|
|
497
499
|
Propellant initial mass in kg.
|
|
498
500
|
"""
|
|
499
501
|
|
|
502
|
+
@property
|
|
503
|
+
def structural_mass_ratio(self):
|
|
504
|
+
"""Calculates the structural mass ratio. The ratio is defined as
|
|
505
|
+
the dry mass divided by the initial total mass.
|
|
506
|
+
|
|
507
|
+
Returns
|
|
508
|
+
-------
|
|
509
|
+
float
|
|
510
|
+
Initial structural mass ratio.
|
|
511
|
+
"""
|
|
512
|
+
initial_total_mass = self.dry_mass + self.propellant_initial_mass
|
|
513
|
+
try:
|
|
514
|
+
return self.dry_mass / initial_total_mass
|
|
515
|
+
except ZeroDivisionError as e:
|
|
516
|
+
raise ValueError(
|
|
517
|
+
"Total motor mass (dry + propellant) cannot be zero"
|
|
518
|
+
) from e
|
|
519
|
+
|
|
500
520
|
@funcify_method("Time (s)", "Motor center of mass (m)")
|
|
501
521
|
def center_of_mass(self):
|
|
502
522
|
"""Position of the center of mass as a function of time. The position
|
|
@@ -1502,6 +1522,7 @@ class EmptyMotor:
|
|
|
1502
1522
|
self.nozzle_radius = 0
|
|
1503
1523
|
self.thrust = Function(0, "Time (s)", "Thrust (N)")
|
|
1504
1524
|
self.propellant_mass = Function(0, "Time (s)", "Propellant Mass (kg)")
|
|
1525
|
+
self.propellant_initial_mass = 0
|
|
1505
1526
|
self.total_mass = Function(0, "Time (s)", "Total Mass (kg)")
|
|
1506
1527
|
self.total_mass_flow_rate = Function(
|
|
1507
1528
|
0, "Time (s)", "Mass Depletion Rate (kg/s)"
|
|
@@ -70,6 +70,8 @@ class SolidMotor(Motor):
|
|
|
70
70
|
of propellant and dry mass.
|
|
71
71
|
SolidMotor.propellant_mass : Function
|
|
72
72
|
Total propellant mass in kg as a function of time.
|
|
73
|
+
SolidMotor.structural_mass_ratio: float
|
|
74
|
+
Initial ratio between the dry mass and the total mass.
|
|
73
75
|
SolidMotor.total_mass_flow_rate : Function
|
|
74
76
|
Time derivative of propellant total mass in kg/s as a function
|
|
75
77
|
of time as obtained by the thrust source.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import matplotlib.pyplot as plt
|
|
2
|
+
import numpy as np
|
|
2
3
|
|
|
3
4
|
from ..tools import generate_monte_carlo_ellipses, import_optional_dependency
|
|
4
5
|
|
|
@@ -54,14 +55,30 @@ class _MonteCarloPlots:
|
|
|
54
55
|
"The image file was not found. Please check the path."
|
|
55
56
|
) from e
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
try:
|
|
59
|
+
apogee_x = np.array(self.monte_carlo.results["apogee_x"])
|
|
60
|
+
apogee_y = np.array(self.monte_carlo.results["apogee_y"])
|
|
61
|
+
except KeyError:
|
|
62
|
+
print("No apogee data found. Skipping apogee ellipses.")
|
|
63
|
+
apogee_x = np.array([])
|
|
64
|
+
apogee_y = np.array([])
|
|
65
|
+
try:
|
|
66
|
+
impact_x = np.array(self.monte_carlo.results["x_impact"])
|
|
67
|
+
impact_y = np.array(self.monte_carlo.results["y_impact"])
|
|
68
|
+
except KeyError:
|
|
69
|
+
print("No impact data found. Skipping impact ellipses.")
|
|
70
|
+
impact_x = np.array([])
|
|
71
|
+
impact_y = np.array([])
|
|
72
|
+
|
|
73
|
+
if len(apogee_x) == 0 and len(impact_x) == 0:
|
|
74
|
+
raise ValueError("No apogee or impact data found. Cannot plot ellipses.")
|
|
75
|
+
|
|
76
|
+
impact_ellipses, apogee_ellipses = generate_monte_carlo_ellipses(
|
|
60
77
|
apogee_x,
|
|
61
78
|
apogee_y,
|
|
62
79
|
impact_x,
|
|
63
80
|
impact_y,
|
|
64
|
-
)
|
|
81
|
+
)
|
|
65
82
|
|
|
66
83
|
# Create plot figure
|
|
67
84
|
plt.figure(figsize=(8, 6), dpi=150)
|
|
@@ -97,9 +114,7 @@ class _MonteCarloPlots:
|
|
|
97
114
|
)
|
|
98
115
|
|
|
99
116
|
plt.legend()
|
|
100
|
-
ax.set_title(
|
|
101
|
-
"1$\\sigma$, 2$\\sigma$ and 3$\\sigma$ Monte Carlo Ellipses: Apogee and Landing Points"
|
|
102
|
-
)
|
|
117
|
+
ax.set_title("1$\\sigma$, 2$\\sigma$ and 3$\\sigma$ Monte Carlo Ellipses")
|
|
103
118
|
ax.set_ylabel("North (m)")
|
|
104
119
|
ax.set_xlabel("East (m)")
|
|
105
120
|
|
|
@@ -77,6 +77,7 @@ class _HybridMotorPrints:
|
|
|
77
77
|
print(
|
|
78
78
|
f"Total Propellant Mass: {self.hybrid_motor.propellant_initial_mass:.3f} kg"
|
|
79
79
|
)
|
|
80
|
+
print(f"Structural Mass Ratio: {self.hybrid_motor.structural_mass_ratio:.3f}")
|
|
80
81
|
avg = self.hybrid_motor.exhaust_velocity.average(*self.hybrid_motor.burn_time)
|
|
81
82
|
print(f"Average Propellant Exhaust Velocity: {avg:.3f} m/s")
|
|
82
83
|
print(f"Average Thrust: {self.hybrid_motor.average_thrust:.3f} N")
|
|
@@ -47,6 +47,7 @@ class _LiquidMotorPrints:
|
|
|
47
47
|
print(
|
|
48
48
|
f"Total Propellant Mass: {self.liquid_motor.propellant_initial_mass:.3f} kg"
|
|
49
49
|
)
|
|
50
|
+
print(f"Structural Mass Ratio: {self.liquid_motor.structural_mass_ratio:.3f}")
|
|
50
51
|
avg = self.liquid_motor.exhaust_velocity.average(*self.liquid_motor.burn_time)
|
|
51
52
|
print(f"Average Propellant Exhaust Velocity: {avg:.3f} m/s")
|
|
52
53
|
print(f"Average Thrust: {self.liquid_motor.average_thrust:.3f} N")
|
|
@@ -35,6 +35,7 @@ class _MotorPrints:
|
|
|
35
35
|
print("Motor Details")
|
|
36
36
|
print("Total Burning Time: " + str(self.motor.burn_out_time) + " s")
|
|
37
37
|
print(f"Total Propellant Mass: {self.motor.propellant_initial_mass:.3f} kg")
|
|
38
|
+
print(f"Structural Mass Ratio: {self.motor.structural_mass_ratio:.3f}")
|
|
38
39
|
print(
|
|
39
40
|
"Average Propellant Exhaust Velocity: "
|
|
40
41
|
f"{self.motor.exhaust_velocity.average(*self.motor.burn_time):.3f} m/s"
|