Skip to content

ENH: add Folium interactive flight trajectory map (#963) - #1132

Merged
Gui-FernandesBR merged 4 commits into
RocketPy-Team:developfrom
thatrandomasiandev:enh/963-folium-trajectory-map
Sep 14, 2026
Merged

ENH: add Folium interactive flight trajectory map (#963)#1132
Gui-FernandesBR merged 4 commits into
RocketPy-Team:developfrom
thatrandomasiandev:enh/963-folium-trajectory-map

Conversation

@thatrandomasiandev

Copy link
Copy Markdown

Summary

  • Add Flight.plots.trajectory_on_map() using optional Folium to render an interactive HTML map of the ground track with launch and landing markers.
  • Introduce a maps optional dependency extra (folium) and include it in rocketpy[all].
  • Add unit tests that mock Folium when absent and exercise real HTML export when Folium is installed.

Fixes #963

Test plan

  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 pytest tests/unit/test_flight_trajectory_map.py
  • Smoke: flight.plots.trajectory_on_map(filename="traj.html") opens in a browser with path + markers

@thatrandomasiandev
thatrandomasiandev requested a review from a team as a code owner August 11, 2026 01:46
@Gui-FernandesBR
Gui-FernandesBR force-pushed the enh/963-folium-trajectory-map branch from bf9ce35 to 2f52628 Compare August 15, 2026 01:47
@Gui-FernandesBR Gui-FernandesBR linked an issue Aug 15, 2026 that may be closed by this pull request
2 tasks
@Gui-FernandesBR
Gui-FernandesBR marked this pull request as draft August 15, 2026 01:47
@Gui-FernandesBR

Copy link
Copy Markdown
Member

There are many other ways of implementing this one. We need first to reflect on that.

@codecov

codecov Bot commented Aug 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.87500% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.43%. Comparing base (88aed5a) to head (ed3e9e9).

Files with missing lines Patch % Lines
rocketpy/plots/flight_plots.py 96.87% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #1132      +/-   ##
===========================================
+ Coverage    91.41%   91.43%   +0.01%     
===========================================
  Files          132      132              
  Lines        18133    18197      +64     
===========================================
+ Hits         16577    16639      +62     
- Misses        1556     1558       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Gui-FernandesBR and others added 3 commits September 13, 2026 23:18
Carries over the conventions from the team's internal rocketfolium module
(EuRoC-Dev) into Flight.plots.trajectory_on_map, and fills the gaps that
kept PR RocketPy-Team#1132 in draft.

Map rendering:
- Add OpenStreetMap and Esri World Imagery background layers behind a
  LayerControl. Satellite imagery is what actually answers the recovery
  question (terrain, tree lines, water), which plain OSM cannot show.
- Mark the apogee ground position, labelled with apogee AGL, between the
  launch and landing markers. Skipped when apogee was never detected,
  since Flight.apogee_time then keeps its initial value of zero.
- Add optional range safety circles around the launch pad, in their own
  feature group so the layer control can toggle them. The initial
  viewport widens to contain them, otherwise the largest ring would open
  off screen and the parameter would be useless.
- Add an optional overlay title. The text is HTML-escaped before being
  injected into the map root.

API:
- Add time_step, for parity with Flight.export_kml: the ground track is
  resampled by linear interpolation instead of drawing every integration
  step, which keeps the HTML small for long flights.
- Add color, so the track can be recoloured without post-processing.

Docs:
- Document the maps extra in installation.rst, next to the animation
  extra it mirrors.
- Add an "Interactive Trajectory Map" section to the Flight user guide,
  with the parameter table and a cross-reference to export_kml for the
  3D case that a 2D map cannot cover.

Verified: 10/10 unit tests pass (including the real-folium HTML export),
ruff clean, pylint 10.00/10, and sphinx-build -W builds with zero
warnings. The rendered map was checked in a browser.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Pad the fitted viewport by 30 px so the launch and landing pins, anchored
at the very edge of the bounding box, are no longer clipped by the map
border. Caught while rendering the screenshots below.

Add two figures to the Flight user guide, captured from the real output:
the ground track with the launch, apogee and landing markers over
satellite imagery, and the safety_radii circles framed around the pad.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Gui-FernandesBR

Copy link
Copy Markdown
Member

Hi @thatrandomasiandev — thanks for the patience on this one, and sorry for the long silence after my "there are many other ways of implementing this" comment. That was a vague thing to say without following up, so let me make it concrete.

Back in #963 I mentioned we had internal tooling that already does Folium maps. That's a module we use to produce the impact maps for EuRoC, and rather than keep asking you to guess at our conventions, I've pushed the port directly onto your branch (fast-forward, nothing of yours rewritten). Please pull before you continue.

What I changed

Your structure was right — the optional-dependency handling, the maps extra, and the plots.trajectory_on_map() placement all match how the codebase does things. What it was missing was the rocketry-specific part:

  • Satellite imagery. Plain OpenStreetMap can't answer the question you actually ask a map of a rocket flight — what's the terrain, where are the tree lines, is there water. The map now ships OpenStreetMap and Esri World Imagery behind a LayerControl, with satellite active by default.
  • Apogee marker, labelled with apogee AGL, between launch and landing. Skipped when apogee was never detected, since Flight.apogee_time keeps its initial value of 0 and the marker would otherwise land on the pad.
  • safety_radii — range safety circles around the pad, in their own toggleable layer. This is the feature our internal tooling exists for.
  • time_step, for parity with Flight.export_kml: resample the ground track instead of drawing every integration step.
  • color and title (the title is HTML-escaped before injection).

Ground track over satellite imagery

Launch (green), apogee ground position (blue), landing (red).

Range safety circles

safety_radii=[2500, 5000]. Two bugs turned up only by looking at this render: the fitted viewport ignored the circles, so asking for a 5 km ring gave you a screen with no ring on it; and the launch/landing pins were clipped by the map border because the bounding box has no padding. Both fixed.

Other gaps closed

  • Docs. This was the real blocker. The maps extra was in pyproject.toml but documented nowhere — installation.rst and flight.rst both have sections for the animation extra and had none for this. Both now do, including a parameter table and a cross-reference to export_kml for the 3D case a 2D map can't cover.
  • Branch was 40 commits behind develop. Merged, no conflicts.
  • Tests: 4 → 10, covering the tile layers, the apogee marker and its skip path, the safety circles and their framing, title escaping, and time_step resampling.

On the red build-docs (3.12)

That check is stale, not a real failure — the current docs.yml only triggers for PRs based on master, and this one targets develop. The logs have expired (HTTP 410) so I couldn't read the original. I ran the docs build locally anyway, exactly as CI does, since this reaches master eventually.

Verification

sphinx-build -W --keep-going exits 0 with zero warnings, 10/10 unit tests pass including the real-Folium HTML export, ruff clean, pylint 10.00/10. The maps above are the actual rendered output, checked in a browser.

Still open, and worth your call

The bigger prize from the internal module is the Monte Carlo impact map — numbered markers coloured by outcome (nominal / ballistic / main-at-apogee), a dynamic legend, and a distance grid. That belongs on MonteCarlo.plots, not on Flight, so it should be a separate issue rather than growing this PR. Happy to open it if you'd like to take it too.

From my side this is ready to come out of draft. Let me know if you disagree with any of the choices above — particularly satellite-as-default-layer, which is a judgement call.

@Gui-FernandesBR
Gui-FernandesBR marked this pull request as ready for review September 14, 2026 02:56
@Gui-FernandesBR
Gui-FernandesBR merged commit 9fbf3a3 into RocketPy-Team:develop Sep 14, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Folium support for interactive trajectory maps

2 participants