OpenAP Trajectory Optimizer

Currently, almost all flight optimizers proposed in the literature stay close-sourced, which presents a major disadvantage for the advancement of scientific research.

OpenAP trajectory optimizer ( is going to change this. It offers researchers easy access to the complex but efficient direct collocation optimization approach. The optimizer adapts to meteorological conditions and can be employed in different flight phases separately or combined. It includes conventional fuel and cost index objectives, as well as climate metrics-based objectives using global warming or temperature potential.

Install uses cfgrib for integrating wind data, cartopy for plotting, and a few other libraries. I recommend using conda to install these dependencies. Following is an example how I set it up on my computer for testing.

  1. Create a new conda environmental (openap), which avoids messing up the base conda environment:
    conda create -n openap python=3.10 -c conda-forge
  2. Use the openap environment
    conda activate openap
  3. Install dependent libraries:
    conda install cfgrib cartopy
  4. Install the most recent version of openap:
    pip install --upgrade git+
  5. Install the most recent version of openap-top:
    pip install --upgrade git+

Quick start

Example code to generate a fuel optimal flight between two airports:

import as otop

optimizer = otop.CompleteFlight("A320", "EHAM", "LGAV", m0=0.85)

flight = optimizer.trajectory(objective="fuel")

You can specify different objective functions as:

flight = optimizer.trajectory(objective="ci:30")
flight = optimizer.trajectory(objective="gwp100")
flight = optimizer.trajectory(objective="gtp100")

The final flight object is a pandas DataFrame.

Use wind data

To enable wind in your optimizer, you must first download meteorological data in grib format from ECMWF, for example, the ERA5 data at

Then enable the wind for the defined optimizer.

Example code:

import as otop

optimizer = otop.CompleteFlight("A320", "EHAM", "LGAV", m0=0.85)

fgrib = "path_to_the_wind_data.grib"
windfield = top.wind.read_grib(fgrib)

flight = optimizer.trajectory(objective="fuel")

If your grib file includes multiple timestamps, make sure to filter the correct time in the previous windfield object (pandas DataFrame).

Example of an optimal flight:

Visualization of the previous flight using matplotlib and cartopy: