Skip to content

Commit

Permalink
BUG: fix export ellipses to kml function
Browse files Browse the repository at this point in the history
  • Loading branch information
Gui-FernandesBR committed Oct 12, 2024
1 parent 2b63cd9 commit 5208984
Show file tree
Hide file tree
Showing 8 changed files with 2,358 additions and 2,259 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"elevation": 113, "gravity": "'Function from R1 to R1 : (height (m)) \u2192 (gravity (m/s\u00b2))'", "latitude": 39.3897, "longitude": -8.288964, "wind_velocity_x_factor": 1.0, "wind_velocity_y_factor": 1.0, "datum": "SIRGAS2000", "timezone": "UTC", "ensemble_member": 12, "radius": 0.0635026504073287, "mass": 15.682085969389227, "I_11_without_motor": 6.321, "I_22_without_motor": 6.338988882158036, "I_33_without_motor": 0.03130204348386302, "I_12_without_motor": 0, "I_13_without_motor": 0, "I_23_without_motor": 0, "power_off_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power Off)'", "power_on_drag": "'Function from R1 to R1 : (Mach Number) \u2192 (Drag Coefficient with Power On)'", "power_off_drag_factor": 1.0, "power_on_drag_factor": 1.0, "center_of_mass_without_motor": 0.0, "coordinate_system_orientation": "tail_to_nose", "parachutes": [{"cd_s": 9.964579481480238, "trigger": 800, "sampling_rate": 105, "lag": 1.5400928421750208, "noise": [0, 8.3, 0.5], "name": "Main"}, {"cd_s": 1.053581347292585, "trigger": "apogee", "sampling_rate": 105, "lag": 1.547076677223584, "noise": [0, 8.3, 0.5], "name": "Drogue"}], "motors": [{"thrust_source": [[0, 0], [0.055, 100.0], [0.092, 1500.0], [0.1, 2000.0], [0.15, 2200.0], [0.2, 1800.0], [0.5, 1950.0], [1.0, 2034.0], [1.5, 2000.0], [2.0, 1900.0], [2.5, 1760.0], [2.9, 1700.0], [3.0, 1650.0], [3.3, 530.0], [3.4, 350.0], [3.9, 0.0]], "total_impulse": 6856.354770975974, "burn_start_time": 0, "burn_out_time": 3.9, "dry_mass": 1.815, "dry_I_11": 0.125, "dry_I_22": 0.125, "dry_I_33": 0.002, "dry_I_12": 0, "dry_I_13": 0, "dry_I_23": 0, "nozzle_radius": 0.032730650070270366, "grain_number": 5, "grain_density": 1759.0002074492309, "grain_outer_radius": 0.03242230462181787, "grain_initial_inner_radius": 0.014932033668244029, "grain_initial_height": 0.11986670781368569, "grain_separation": 0.0043804774372666125, "grains_center_of_mass_position": 0.39749334004739806, "center_of_dry_mass_position": 0.317, "nozzle_position": 0.00012776739944301812, "throat_radius": 0.011558987272317063, "interpolate": "linear", "coordinate_system_orientation": "nozzle_to_combustion_chamber", "position": -1.2554668494646906}], "aerodynamic_surfaces": [{"length": 0.5585738309196118, "kind": "vonKarman", "base_radius": 0.0635, "bluffness": 0, "rocket_radius": 0.0635, "name": "Nose Cone", "position": [0, 0, 1.133607250248703]}, {"n": 4, "root_chord": 0.11954751546671595, "tip_chord": 0.05966602935963838, "span": 0.10964031934715668, "rocket_radius": 0.0635, "cant_angle": 0.5, "sweep_length": 0.06, "sweep_angle": null, "airfoil": ["../../../data/calisto/NACA0012-radians.csv", "radians"], "name": "Fins", "position": [0, 0, -1.0514983708842365]}, {"top_radius": 0.06343918078680816, "bottom_radius": 0.04325007199856578, "length": 0.060394317313238605, "rocket_radius": 0.0635, "name": "Tail", "position": [0, 0, [0, 0, -1.194656]]}], "rail_buttons": [{"buttons_distance": 0.6974746622933771, "angular_position": 45, "name": "Rail Buttons", "lower_button_position": -0.6188258915052254, "upper_button_position": 0.07864877078815169}], "rail_length": 5, "inclination": 84.44167248190685, "heading": 54.43860091183173}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

484 changes: 440 additions & 44 deletions docs/notebooks/monte_carlo_analysis/monte_carlo_class_usage.ipynb

Large diffs are not rendered by default.

26 changes: 19 additions & 7 deletions rocketpy/plots/monte_carlo_plots.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import matplotlib.pyplot as plt
import numpy as np

from ..tools import generate_monte_carlo_ellipses, import_optional_dependency

Expand Down Expand Up @@ -54,14 +55,27 @@ def ellipses(
"The image file was not found. Please check the path."
) from e

(
impact_ellipses,
apogee_ellipses,
try:
apogee_x = np.array(self.monte_carlo.results["apogee_x"])
apogee_y = np.array(self.monte_carlo.results["apogee_y"])
except KeyError:
print("No apogee data found. Skipping apogee ellipses.")
apogee_x = np.array([])
apogee_y = np.array([])

Check warning on line 64 in rocketpy/plots/monte_carlo_plots.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/plots/monte_carlo_plots.py#L61-L64

Added lines #L61 - L64 were not covered by tests
try:
impact_x = np.array(self.monte_carlo.results["x_impact"])
impact_y = np.array(self.monte_carlo.results["y_impact"])
except KeyError:
print("No impact data found. Skipping impact ellipses.")
impact_x = np.array([])
impact_y = np.array([])

Check warning on line 71 in rocketpy/plots/monte_carlo_plots.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/plots/monte_carlo_plots.py#L68-L71

Added lines #L68 - L71 were not covered by tests

impact_ellipses, apogee_ellipses = generate_monte_carlo_ellipses(
apogee_x,
apogee_y,
impact_x,
impact_y,
) = generate_monte_carlo_ellipses(self.monte_carlo.results)
)

# Create plot figure
plt.figure(figsize=(8, 6), dpi=150)
Expand Down Expand Up @@ -97,9 +111,7 @@ def ellipses(
)

plt.legend()
ax.set_title(
"1$\\sigma$, 2$\\sigma$ and 3$\\sigma$ Monte Carlo Ellipses: Apogee and Landing Points"
)
ax.set_title("1$\\sigma$, 2$\\sigma$ and 3$\\sigma$ Monte Carlo Ellipses")
ax.set_ylabel("North (m)")
ax.set_xlabel("East (m)")

Expand Down
92 changes: 66 additions & 26 deletions rocketpy/simulation/monte_carlo.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ def export_ellipses_to_kml( # pylint: disable=too-many-statements
origin_lon,
type="all", # TODO: Don't use "type" as a parameter name, it's a reserved word # pylint: disable=redefined-builtin
resolution=100,
color="ff0000ff",
colors=("ffff0000", "ff00ff00"), # impact, apogee
):
"""
Generates a KML file with the ellipses on the impact point, which can be
Expand All @@ -793,9 +793,11 @@ def export_ellipses_to_kml( # pylint: disable=too-many-statements
Number of points to be used to draw the ellipse. Default is 100. You
can increase this number to make the ellipse smoother, but it will
increase the file size. It is recommended to keep it below 1000.
color : str, optional
Color of the ellipse. Default is 'ff0000ff', which is red. Kml files
use an 8 digit HEX color format, see its docs.
colors : tuple[str, str], optional
Colors of the ellipses. Default is ['ffff0000', 'ff00ff00'], which
are blue and green, respectively. The first element is the color of
the impact ellipses, and the second element is the color of the
apogee. The colors are in hexadecimal format (aabbggrr).
Returns
-------
Expand All @@ -812,50 +814,88 @@ def export_ellipses_to_kml( # pylint: disable=too-many-statements
large distances offsets, as the atmospheric conditions may change.
"""
# TODO: The lat and lon should be optional arguments, we can get it from the env
(
impact_ellipses,
apogee_ellipses,
*_,
) = generate_monte_carlo_ellipses(self.results)
# Retrieve monte carlo data por apogee and impact XY position
if type not in ["all", "impact", "apogee"]:
raise ValueError("Invalid type. Options are 'all', 'impact' and 'apogee'")

Check warning on line 819 in rocketpy/simulation/monte_carlo.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/simulation/monte_carlo.py#L819

Added line #L819 was not covered by tests

apogee_x = np.array([])
apogee_y = np.array([])
impact_x = np.array([])
impact_y = np.array([])
if type in ["all", "apogee"]:
try:
apogee_x = np.array(self.results["apogee_x"])
apogee_y = np.array(self.results["apogee_y"])
except KeyError as e:
raise KeyError("No apogee data found. Skipping apogee ellipses.") from e

Check warning on line 830 in rocketpy/simulation/monte_carlo.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/simulation/monte_carlo.py#L826-L830

Added lines #L826 - L830 were not covered by tests

if type in ["all", "impact"]:
try:
impact_x = np.array(self.results["x_impact"])
impact_y = np.array(self.results["y_impact"])
except KeyError as e:
raise KeyError("No impact data found. Skipping impact ellipses.") from e

Check warning on line 837 in rocketpy/simulation/monte_carlo.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/simulation/monte_carlo.py#L836-L837

Added lines #L836 - L837 were not covered by tests

(apogee_ellipses, impact_ellipses) = generate_monte_carlo_ellipses(
impact_x,
impact_y,
apogee_x,
apogee_y,
)

outputs = []

if type in ["all", "impact"]:
outputs = outputs + generate_monte_carlo_ellipses_coordinates(
impact_ellipses, origin_lat, origin_lon, resolution=resolution
outputs.extend(
generate_monte_carlo_ellipses_coordinates(
impact_ellipses, origin_lat, origin_lon, resolution=resolution
)
)

if type in ["all", "apogee"]:
outputs = outputs + generate_monte_carlo_ellipses_coordinates(
apogee_ellipses, origin_lat, origin_lon, resolution=resolution
outputs.extend(

Check warning on line 856 in rocketpy/simulation/monte_carlo.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/simulation/monte_carlo.py#L856

Added line #L856 was not covered by tests
generate_monte_carlo_ellipses_coordinates(
apogee_ellipses, origin_lat, origin_lon, resolution=resolution
)
)

# TODO: Non-iterable value output is used in an iterating context PylintE1133:
kml_data = [[(coord[1], coord[0]) for coord in output] for output in outputs]
if all(isinstance(output, list) for output in outputs):
kml_data = [
[(coord[1], coord[0]) for coord in output] for output in outputs
]
else:
raise ValueError("Each element in outputs must be a list")

Check warning on line 867 in rocketpy/simulation/monte_carlo.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/simulation/monte_carlo.py#L867

Added line #L867 was not covered by tests

kml = simplekml.Kml()

for i in range(len(outputs)):
if (type == "all" and i < 3) or (type == "impact"):
ellipse_name = "Impact \u03C3" + str(i + 1)
elif type == "all" and i >= 3:
ellipse_name = "Apogee \u03C3" + str(i - 2)
for i, points in enumerate(kml_data):
if i < len(impact_ellipses):
name = f"Impact Ellipse {i+1}"
ellipse_color = colors[0] # default is blue
else:
ellipse_name = "Apogee \u03C3" + str(i + 1)
name = f"Apogee Ellipse {i +1- len(impact_ellipses)}"
ellipse_color = colors[1] # default is green

Check warning on line 877 in rocketpy/simulation/monte_carlo.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/simulation/monte_carlo.py#L876-L877

Added lines #L876 - L877 were not covered by tests

mult_ell = kml.newmultigeometry(name=ellipse_name)
mult_ell = kml.newmultigeometry(name=name)
mult_ell.newpolygon(
outerboundaryis=kml_data[i],
name="Ellipse " + str(i),
outerboundaryis=points,
name=name,
)
# Setting ellipse style
mult_ell.tessellate = 1
mult_ell.visibility = 1
mult_ell.style.linestyle.color = color
mult_ell.style.linestyle.color = ellipse_color
mult_ell.style.linestyle.width = 3
mult_ell.style.polystyle.color = simplekml.Color.changealphaint(
100, simplekml.Color.blue
80, ellipse_color
)

kml.newpoint(
name="Launch Pad",
coords=[(origin_lon, origin_lat)],
description="Flight initial position",
)

kml.save(filename)

def info(self):
Expand Down
Loading

0 comments on commit 5208984

Please sign in to comment.