Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 830ea15

Browse files
committed
ENH: refactor retrieve arrays cached properties and controller sim post processing
1 parent 624cc15 commit 830ea15

File tree

1 file changed

+156
-97
lines changed

1 file changed

+156
-97
lines changed

rocketpy/simulation/flight.py

Lines changed: 156 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,6 @@ def __init__(
593593
if self.rail_length <= 0:
594594
raise ValueError("Rail length must be a positive value.")
595595
self.parachutes = self.rocket.parachutes[:]
596-
self._controllers = self.rocket._controllers[:]
597596
self.inclination = inclination
598597
self.heading = heading
599598
self.max_time = max_time
@@ -607,6 +606,13 @@ def __init__(
607606
self.name = name
608607
self.equations_of_motion = equations_of_motion
609608

609+
# Controller initialization
610+
self._controllers = self.rocket._controllers[:]
611+
if self._controllers:
612+
# reset controllable object to initial state (only airbrakes for now)
613+
for air_brakes in self.rocket.air_brakes:
614+
air_brakes.reset()
615+
610616
# Flight initialization
611617
self.__init_post_process_variables()
612618
self.__init_solution_monitors()
@@ -1076,8 +1082,14 @@ def __init__(
10761082
[self.t, parachute]
10771083
)
10781084

1085+
# If controlled flight, post process must be done on sim time
1086+
if self._controllers:
1087+
phase.derivative(self.t, self.y_sol, post_processing=True)
1088+
10791089
self.t_final = self.t
10801090
self._calculate_pressure_signal()
1091+
if self._controllers:
1092+
self.__cache_post_process_variables()
10811093
if verbose:
10821094
print("Simulation Completed at Time: {:3.4f} s".format(self.t))
10831095

@@ -1089,6 +1101,25 @@ def __init_post_process_variables(self):
10891101
self._bearing = Function(0)
10901102
self._latitude = Function(0)
10911103
self._longitude = Function(0)
1104+
# Initialize state derivatives, force and atmospheric arrays
1105+
self.ax_list = []
1106+
self.ay_list = []
1107+
self.az_list = []
1108+
self.alpha1_list = []
1109+
self.alpha2_list = []
1110+
self.alpha3_list = []
1111+
self.R1_list = []
1112+
self.R2_list = []
1113+
self.R3_list = []
1114+
self.M1_list = []
1115+
self.M2_list = []
1116+
self.M3_list = []
1117+
self.pressure_list = []
1118+
self.density_list = []
1119+
self.dynamic_viscosity_list = []
1120+
self.speed_of_sound_list = []
1121+
self.wind_velocity_x_list = []
1122+
self.wind_velocity_y_list = []
10921123

10931124
def __init_solution_monitors(self):
10941125
# Initialize solution monitors
@@ -1181,10 +1212,28 @@ def __init_equations_of_motion(self):
11811212
if self.equations_of_motion == "solid_propulsion":
11821213
self.u_dot_generalized = self.u_dot
11831214

1184-
def __init_equations_of_motion(self):
1185-
"""Initialize equations of motion."""
1186-
if self.equations_of_motion == "solid_propulsion":
1187-
self.u_dot_generalized = self.u_dot
1215+
def __cache_post_process_variables(self):
1216+
"""Cache post-process variables for simulations with controllers."""
1217+
self.__retrieve_arrays = [
1218+
self.ax_list,
1219+
self.ay_list,
1220+
self.az_list,
1221+
self.alpha1_list,
1222+
self.alpha2_list,
1223+
self.alpha3_list,
1224+
self.R1_list,
1225+
self.R2_list,
1226+
self.R3_list,
1227+
self.M1_list,
1228+
self.M2_list,
1229+
self.M3_list,
1230+
self.pressure_list,
1231+
self.density_list,
1232+
self.dynamic_viscosity_list,
1233+
self.speed_of_sound_list,
1234+
self.wind_velocity_x_list,
1235+
self.wind_velocity_y_list,
1236+
]
11881237

11891238
@cached_property
11901239
def effective_1rl(self):
@@ -1261,11 +1310,6 @@ def udot_rail1(self, t, u, post_processing=False):
12611310
e0dot, e1dot, e2dot, e3dot, alpha1, alpha2, alpha3].
12621311
12631312
"""
1264-
# Check if post processing mode is on
1265-
if post_processing:
1266-
# Use u_dot post processing code
1267-
return self.u_dot_generalized(t, u, True)
1268-
12691313
# Retrieve integration data
12701314
x, y, z, vx, vy, vz, e0, e1, e2, e3, omega1, omega2, omega3 = u
12711315

@@ -1296,6 +1340,17 @@ def udot_rail1(self, t, u, post_processing=False):
12961340
else:
12971341
ax, ay, az = 0, 0, 0
12981342

1343+
if post_processing:
1344+
# Use u_dot post processing code for forces, moments and env data
1345+
self.u_dot_generalized(t, u, post_processing=True)
1346+
# Save feasible accelerations
1347+
self.ax_list[-1] = [t, ax]
1348+
self.ay_list[-1] = [t, ay]
1349+
self.az_list[-1] = [t, az]
1350+
self.alpha1_list[-1] = [t, 0]
1351+
self.alpha2_list[-1] = [t, 0]
1352+
self.alpha3_list[-1] = [t, 0]
1353+
12991354
return [vx, vy, vz, ax, ay, az, 0, 0, 0, 0, 0, 0, 0]
13001355

13011356
def udot_rail2(self, t, u, post_processing=False):
@@ -1585,6 +1640,13 @@ def u_dot(self, t, u, post_processing=False):
15851640
]
15861641

15871642
if post_processing:
1643+
# Accelerations
1644+
self.ax_list.append([t, ax])
1645+
self.ay_list.append([t, ay])
1646+
self.az_list.append([t, az])
1647+
self.alpha1_list.append([t, alpha1])
1648+
self.alpha2_list.append([t, alpha2])
1649+
self.alpha3_list.append([t, alpha3])
15881650
# Dynamics variables
15891651
self.R1_list.append([t, R1])
15901652
self.R2_list.append([t, R2])
@@ -1860,6 +1922,13 @@ def u_dot_generalized(self, t, u, post_processing=False):
18601922
u_dot = [*r_dot, *v_dot, *e_dot, *w_dot]
18611923

18621924
if post_processing:
1925+
# Accelerations
1926+
self.ax_list.append([t, v_dot[0]])
1927+
self.ay_list.append([t, v_dot[1]])
1928+
self.az_list.append([t, v_dot[2]])
1929+
self.alpha1_list.append([t, w_dot[0]])
1930+
self.alpha2_list.append([t, w_dot[1]])
1931+
self.alpha3_list.append([t, w_dot[2]])
18631932
# Dynamics variables
18641933
self.R1_list.append([t, R1])
18651934
self.R2_list.append([t, R2])
@@ -1944,6 +2013,13 @@ def u_dot_parachute(self, t, u, post_processing=False):
19442013
az = (Dz - 9.8 * mp) / (mp + ma)
19452014

19462015
if post_processing:
2016+
# Accelerations
2017+
self.ax_list.append([t, ax])
2018+
self.ay_list.append([t, ay])
2019+
self.az_list.append([t, az])
2020+
self.alpha1_list.append([t, 0])
2021+
self.alpha2_list.append([t, 0])
2022+
self.alpha3_list.append([t, 0])
19472023
# Dynamics variables
19482024
self.R1_list.append([t, Dx])
19492025
self.R2_list.append([t, Dy])
@@ -1952,13 +2028,20 @@ def u_dot_parachute(self, t, u, post_processing=False):
19522028
self.M2_list.append([t, 0])
19532029
self.M3_list.append([t, 0])
19542030
# Atmospheric Conditions
1955-
self.wind_velocity_x_list.append([t, self.env.wind_velocity_x(z)])
1956-
self.wind_velocity_y_list.append([t, self.env.wind_velocity_y(z)])
1957-
self.density_list.append([t, self.env.density(z)])
1958-
self.dynamic_viscosity_list.append([t, self.env.dynamic_viscosity(z)])
1959-
self.pressure_list.append([t, self.env.pressure(z)])
1960-
self.speed_of_sound_list.append([t, self.env.speed_of_sound(z)])
1961-
2031+
self.wind_velocity_x_list.append(
2032+
[t, self.env.wind_velocity_x.get_value_opt(z)]
2033+
)
2034+
self.wind_velocity_y_list.append(
2035+
[t, self.env.wind_velocity_y.get_value_opt(z)]
2036+
)
2037+
self.density_list.append([t, self.env.density.get_value_opt(z)])
2038+
self.dynamic_viscosity_list.append(
2039+
[t, self.env.dynamic_viscosity.get_value_opt(z)]
2040+
)
2041+
self.pressure_list.append([t, self.env.pressure.get_value_opt(z)])
2042+
self.speed_of_sound_list.append(
2043+
[t, self.env.speed_of_sound.get_value_opt(z)]
2044+
)
19622045
return [vx, vy, vz, ax, ay, az, 0, 0, 0, 0, 0, 0, 0]
19632046

19642047
@cached_property
@@ -2790,13 +2873,64 @@ def longitude(self):
27902873

27912874
return np.column_stack((self.time, longitude))
27922875

2876+
@cached_property
2877+
def __retrieve_arrays(self):
2878+
"""post processing function to retrieve arrays from the integration
2879+
scheme and store them in lists for further analysis.
2880+
2881+
Returns
2882+
-------
2883+
temp_values: list
2884+
List containing the following arrays: ``ax`` , ``ay`` , ``az`` ,
2885+
``alpha1`` , ``alpha2`` , ``alpha3`` , ``R1`` , ``R2`` , ``R3`` ,
2886+
``M1`` , ``M2`` , ``M3`` , ``pressure`` , ``density`` ,
2887+
``dynamic_viscosity`` , ``speed_of_sound`` , ``wind_velocity_x`` ,
2888+
``wind_velocity_y``.
2889+
"""
2890+
# Go through each time step and calculate forces and atmospheric values
2891+
# Get flight phases
2892+
for phase_index, phase in self.time_iterator(self.FlightPhases):
2893+
init_time = phase.t
2894+
final_time = self.FlightPhases[phase_index + 1].t
2895+
current_derivative = phase.derivative
2896+
# Call callback functions
2897+
for callback in phase.callbacks:
2898+
callback(self)
2899+
# Loop through time steps in flight phase
2900+
for step in self.solution: # Can be optimized
2901+
if init_time < step[0] <= final_time or (
2902+
init_time == self.t_initial and step[0] == self.t_initial
2903+
):
2904+
# Call derivatives in post processing mode
2905+
current_derivative(step[0], step[1:], post_processing=True)
2906+
2907+
temp_values = [
2908+
self.ax_list,
2909+
self.ay_list,
2910+
self.az_list,
2911+
self.alpha1_list,
2912+
self.alpha2_list,
2913+
self.alpha3_list,
2914+
self.R1_list,
2915+
self.R2_list,
2916+
self.R3_list,
2917+
self.M1_list,
2918+
self.M2_list,
2919+
self.M3_list,
2920+
self.pressure_list,
2921+
self.density_list,
2922+
self.dynamic_viscosity_list,
2923+
self.speed_of_sound_list,
2924+
self.wind_velocity_x_list,
2925+
self.wind_velocity_y_list,
2926+
]
2927+
2928+
return temp_values
2929+
27932930
@cached_property
27942931
def retrieve_acceleration_arrays(self):
27952932
"""Retrieve acceleration arrays from the integration scheme
27962933
2797-
Parameters
2798-
----------
2799-
28002934
Returns
28012935
-------
28022936
ax: list
@@ -2812,35 +2946,7 @@ def retrieve_acceleration_arrays(self):
28122946
alpha3: list
28132947
angular acceleration in z direction
28142948
"""
2815-
# Initialize acceleration arrays
2816-
ax, ay, az = [[0, 0]], [[0, 0]], [[0, 0]]
2817-
alpha1, alpha2, alpha3 = [[0, 0]], [[0, 0]], [[0, 0]]
2818-
# Go through each time step and calculate accelerations
2819-
# Get flight phases
2820-
for phase_index, phase in self.time_iterator(self.FlightPhases):
2821-
init_time = phase.t
2822-
final_time = self.FlightPhases[phase_index + 1].t
2823-
current_derivative = phase.derivative
2824-
# Call callback functions
2825-
for callback in phase.callbacks:
2826-
callback(self)
2827-
# Loop through time steps in flight phase
2828-
for step in self.solution: # Can be optimized
2829-
if init_time < step[0] <= final_time:
2830-
# Get derivatives
2831-
u_dot = current_derivative(step[0], step[1:])
2832-
# Get accelerations
2833-
ax_value, ay_value, az_value = u_dot[3:6]
2834-
alpha1_value, alpha2_value, alpha3_value = u_dot[10:]
2835-
# Save accelerations
2836-
ax.append([step[0], ax_value])
2837-
ay.append([step[0], ay_value])
2838-
az.append([step[0], az_value])
2839-
alpha1.append([step[0], alpha1_value])
2840-
alpha2.append([step[0], alpha2_value])
2841-
alpha3.append([step[0], alpha3_value])
2842-
2843-
return ax, ay, az, alpha1, alpha2, alpha3
2949+
return self.__retrieve_arrays[:6]
28442950

28452951
@cached_property
28462952
def retrieve_temporary_values_arrays(self):
@@ -2877,54 +2983,7 @@ def retrieve_temporary_values_arrays(self):
28772983
self.wind_velocity_y_list: list
28782984
Wind velocity in y direction at each time step.
28792985
"""
2880-
2881-
# Initialize force and atmospheric arrays
2882-
self.R1_list = []
2883-
self.R2_list = []
2884-
self.R3_list = []
2885-
self.M1_list = []
2886-
self.M2_list = []
2887-
self.M3_list = []
2888-
self.pressure_list = []
2889-
self.density_list = []
2890-
self.dynamic_viscosity_list = []
2891-
self.speed_of_sound_list = []
2892-
self.wind_velocity_x_list = []
2893-
self.wind_velocity_y_list = []
2894-
2895-
# Go through each time step and calculate forces and atmospheric values
2896-
# Get flight phases
2897-
for phase_index, phase in self.time_iterator(self.FlightPhases):
2898-
init_time = phase.t
2899-
final_time = self.FlightPhases[phase_index + 1].t
2900-
current_derivative = phase.derivative
2901-
# Call callback functions
2902-
for callback in phase.callbacks:
2903-
callback(self)
2904-
# Loop through time steps in flight phase
2905-
for step in self.solution: # Can be optimized
2906-
if init_time < step[0] <= final_time or (
2907-
init_time == self.t_initial and step[0] == self.t_initial
2908-
):
2909-
# Call derivatives in post processing mode
2910-
u_dot = current_derivative(step[0], step[1:], post_processing=True)
2911-
2912-
temporary_values = [
2913-
self.R1_list,
2914-
self.R2_list,
2915-
self.R3_list,
2916-
self.M1_list,
2917-
self.M2_list,
2918-
self.M3_list,
2919-
self.pressure_list,
2920-
self.density_list,
2921-
self.dynamic_viscosity_list,
2922-
self.speed_of_sound_list,
2923-
self.wind_velocity_x_list,
2924-
self.wind_velocity_y_list,
2925-
]
2926-
2927-
return temporary_values
2986+
return self.__retrieve_arrays[6:]
29282987

29292988
def get_controller_observed_variables(self):
29302989
"""Retrieve the observed variables related to air brakes from the

0 commit comments

Comments
 (0)