Skip to content

Commit 2ebed8d

Browse files
authored
Merge pull request #511 from RocketPy-Team/enh/precalculate-barometric-height
ENH Precalculate Barometric Height
2 parents 821518a + d690f15 commit 2ebed8d

File tree

5 files changed

+74
-9
lines changed

5 files changed

+74
-9
lines changed

.pylintrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ function-naming-style=snake_case
187187
# Good variable names which should always be accepted, separated by a comma.
188188
good-names=FlightPhases,
189189
WindroseAxes,
190+
barometric_height_ISA,
190191

191192

192193
# Good variable names regexes, separated by a comma. If names match any regex,

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ straightforward as possible.
4040
- MNT: Add repr method to Parachute class [#490](https://github.com/RocketPy-Team/RocketPy/pull/490)
4141
- ENH: Function Reverse Arithmetic Priority [#488](https://github.com/RocketPy-Team/RocketPy/pull/488)
4242
- DOC: Update Header Related Docs
43+
- ENH Precalculate Barometric Height [#511](https://github.com/RocketPy-Team/RocketPy/pull/511)
4344
- MNT: Encapsulate quaternion conversions [#537](https://github.com/RocketPy-Team/RocketPy/pull/537)
4445
- MNT: improve the low pass filter and document an example [#538](https://github.com/RocketPy-Team/RocketPy/pull/538)
4546

47+
4648
### Fixed
4749

4850
- ENH: Parachute trigger doesn't work if "Apogee" is used instead of "apogee" [#489](https://github.com/RocketPy-Team/RocketPy/pull/489)

rocketpy/environment/environment.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ class Environment:
111111
Environment.pressure : Function
112112
Air pressure in Pa as a function of altitude. Can be accessed as regular
113113
array, or called as a Function. See Function for more information.
114+
Environment.barometric_height : Function
115+
Geometric height above sea level in m as a function of pressure. Can be
116+
accessed as regular array, or called as a Function. See Function for
117+
more information.
114118
Environment.temperature : Function
115119
Air temperature in K as a function of altitude. Can be accessed as
116120
regular array, or called as a Function. See Function for more
@@ -1315,6 +1319,8 @@ def process_standard_atmosphere(self):
13151319

13161320
# Save temperature, pressure and wind profiles
13171321
self.pressure = self.pressure_ISA
1322+
self.barometric_height = self.barometric_height_ISA
1323+
13181324
self.temperature = self.temperature_ISA
13191325
self.wind_direction = Function(
13201326
0,
@@ -1433,6 +1439,7 @@ def process_custom_atmosphere(
14331439
if pressure is None:
14341440
# Use standard atmosphere
14351441
self.pressure = self.pressure_ISA
1442+
self.barometric_height = self.barometric_height_ISA
14361443
else:
14371444
# Use custom input
14381445
self.pressure = Function(
@@ -1441,6 +1448,11 @@ def process_custom_atmosphere(
14411448
outputs="Pressure (Pa)",
14421449
interpolation="linear",
14431450
)
1451+
self.barometric_height = self.pressure.inverse_function().set_discrete(
1452+
0, max_expected_height, 100, extrapolation="constant"
1453+
)
1454+
self.barometric_height.set_inputs("Pressure (Pa)")
1455+
self.barometric_height.set_outputs("Height Above Sea Level (m)")
14441456
# Check maximum height of custom pressure input
14451457
if not callable(self.pressure.source):
14461458
max_expected_height = max(self.pressure[-1, 0], max_expected_height)
@@ -1605,6 +1617,15 @@ def process_windy_atmosphere(self, model="ECMWF"):
16051617
outputs="Pressure (Pa)",
16061618
interpolation="linear",
16071619
)
1620+
# Linearly extrapolate pressure to ground level
1621+
bar_height = data_array[:, (0, 1)]
1622+
self.barometric_height = Function(
1623+
bar_height,
1624+
inputs="Pressure (Pa)",
1625+
outputs="Height Above Sea Level (m)",
1626+
interpolation="linear",
1627+
extrapolation="natural",
1628+
)
16081629
self.temperature = Function(
16091630
data_array[:, (1, 2)],
16101631
inputs="Height Above Sea Level (m)",
@@ -1732,6 +1753,15 @@ def process_wyoming_sounding(self, file):
17321753
outputs="Pressure (Pa)",
17331754
interpolation="linear",
17341755
)
1756+
# Linearly extrapolate pressure to ground level
1757+
bar_height = data_array[:, (0, 1)]
1758+
self.barometric_height = Function(
1759+
bar_height,
1760+
inputs="Pressure (Pa)",
1761+
outputs="Height Above Sea Level (m)",
1762+
interpolation="linear",
1763+
extrapolation="natural",
1764+
)
17351765

17361766
# Retrieve temperature from data array
17371767
data_array[:, 2] = data_array[:, 2] + 273.15 # Converts C to K
@@ -1845,6 +1875,7 @@ def process_noaaruc_sounding(self, file):
18451875

18461876
# Extract pressure as a function of height
18471877
pressure_array = []
1878+
barometric_height_array = []
18481879
for line in lines:
18491880
# Split line into columns
18501881
columns = re.split(" +", line)[1:]
@@ -1858,7 +1889,9 @@ def process_noaaruc_sounding(self, file):
18581889
if max(columns) != 99999:
18591890
# Save value
18601891
pressure_array.append(columns)
1892+
barometric_height_array.append([columns[1], columns[0]])
18611893
pressure_array = np.array(pressure_array)
1894+
barometric_height_array = np.array(barometric_height_array)
18621895

18631896
# Extract temperature as a function of height
18641897
temperature_array = []
@@ -1905,6 +1938,15 @@ def process_noaaruc_sounding(self, file):
19051938
outputs="Pressure (Pa)",
19061939
interpolation="linear",
19071940
)
1941+
# Converts 10*hPa to Pa and save values
1942+
barometric_height_array[:, 0] = 10 * barometric_height_array[:, 0]
1943+
self.barometric_height = Function(
1944+
barometric_height_array,
1945+
inputs="Pressure (Pa)",
1946+
outputs="Height Above Sea Level (m)",
1947+
interpolation="linear",
1948+
extrapolation="natural",
1949+
)
19081950

19091951
# Convert 10*C to K and save values
19101952
temperature_array[:, 1] = (
@@ -2274,6 +2316,15 @@ def process_forecast_reanalysis(self, file, dictionary):
22742316
outputs="Pressure (Pa)",
22752317
interpolation="linear",
22762318
)
2319+
# Linearly extrapolate pressure to ground level
2320+
bar_height = data_array[:, (0, 1)]
2321+
self.barometric_height = Function(
2322+
bar_height,
2323+
inputs="Pressure (Pa)",
2324+
outputs="Height Above Sea Level (m)",
2325+
interpolation="linear",
2326+
extrapolation="natural",
2327+
)
22772328
self.temperature = Function(
22782329
data_array[:, (1, 2)],
22792330
inputs="Height Above Sea Level (m)",
@@ -2803,6 +2854,15 @@ def select_ensemble_member(self, member=0):
28032854
outputs="Pressure (Pa)",
28042855
interpolation="linear",
28052856
)
2857+
# Linearly extrapolate pressure to ground level
2858+
bar_height = data_array[:, (0, 1)]
2859+
self.barometric_height = Function(
2860+
bar_height,
2861+
inputs="Pressure (Pa)",
2862+
outputs="Height Above Sea Level (m)",
2863+
interpolation="linear",
2864+
extrapolation="natural",
2865+
)
28062866
self.temperature = Function(
28072867
data_array[:, (1, 2)],
28082868
inputs="Height Above Sea Level (m)",
@@ -2965,7 +3025,12 @@ def pressure_function(h):
29653025
outputs="Pressure (Pa)",
29663026
)
29673027

2968-
return None
3028+
# Discretize Function to speed up the trajectory simulation.
3029+
self.barometric_height_ISA = self.pressure_ISA.inverse_function().set_discrete(
3030+
pressure[-1], pressure[0], 100, extrapolation="constant"
3031+
)
3032+
self.barometric_height_ISA.set_inputs("Pressure (Pa)")
3033+
self.barometric_height_ISA.set_outputs("Height Above Sea Level (m)")
29693034

29703035
def calculate_density_profile(self):
29713036
"""Compute the density of the atmosphere as a function of

rocketpy/simulation/flight.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -702,10 +702,7 @@ def __init__(
702702
parachute.noisy_pressure_signal.append([node.t, pressure + noise])
703703
# Gets height above ground level considering noise
704704
hAGL = (
705-
self.env.pressure.find_input(
706-
pressure + noise,
707-
self.y_sol[2],
708-
)
705+
self.env.barometric_height(pressure + noise)
709706
- self.env.elevation
710707
)
711708
if parachute.triggerfunc(pressure + noise, hAGL, self.y_sol):
@@ -1011,10 +1008,7 @@ def __init__(
10111008
)
10121009
# Gets height above ground level considering noise
10131010
hAGL = (
1014-
self.env.pressure.find_input(
1015-
pressure + noise,
1016-
overshootable_node.y[2],
1017-
)
1011+
self.env.barometric_height(pressure + noise)
10181012
- self.env.elevation
10191013
)
10201014

tests/test_environment.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def test_standard_atmosphere(mock_show, example_env):
2020
assert example_env.info() == None
2121
assert example_env.all_info() == None
2222
assert abs(example_env.pressure(0) - 101325.0) < 1e-8
23+
assert abs(example_env.barometric_height(101325.0)) < 1e-2
2324
assert example_env.prints.print_earth_details() == None
2425

2526

@@ -43,6 +44,7 @@ def test_custom_atmosphere(mock_show, example_env):
4344
)
4445
assert example_env.all_info() == None
4546
assert abs(example_env.pressure(0) - 101325.0) < 1e-8
47+
assert abs(example_env.barometric_height(101325.0)) < 1e-2
4648
assert abs(example_env.wind_velocity_x(0) - 5) < 1e-8
4749
assert abs(example_env.temperature(100) - 300) < 1e-8
4850

@@ -71,6 +73,7 @@ def test_wyoming_sounding_atmosphere(mock_show, example_env):
7173
pass
7274
assert example_env.all_info() == None
7375
assert abs(example_env.pressure(0) - 93600.0) < 1e-8
76+
assert abs(example_env.barometric_height(example_env.pressure(0)) - 722.0) < 1e-8
7477
assert abs(example_env.wind_velocity_x(0) - -2.9005178894925043) < 1e-8
7578
assert abs(example_env.temperature(100) - 291.75) < 1e-8
7679

0 commit comments

Comments
 (0)