8  Add-ons

OpenAP can interface with EUROCONTROL’s BADA (Base of Aircraft Data) performance models. Both BADA3 and BADA4 are supported, providing alternative drag, thrust, and fuel flow calculations.

Important

To use these modules, you must first obtain a license and BADA data from EUROCONTROL.

8.1 BADA3

BADA3 uses a coefficient-based model with different parameters for various flight phases. The data is stored in OPF (Operations Performance File) format.

8.1.1 Setup

from openap.addon import bada3

bada_path = "path/to/bada_3.x"

8.1.2 Drag

Calculate drag force in clean and non-clean configurations:

drag = bada3.Drag("A320", bada_path)

# Clean configuration (cruise)
drag.clean(mass=60000, tas=300, alt=35_000)  # kg, kts, ft -> N

# Non-clean configuration (approach or landing)
drag.nonclean(mass=60000, tas=150, alt=3_000, phase="AP")  # approach
drag.nonclean(mass=60000, tas=140, alt=1_000, phase="LD", landing_gear=True)  # landing

The phase parameter accepts:

  • "AP" - Approach configuration
  • "LD" - Landing configuration

8.1.3 Thrust

BADA3 provides thrust calculations for different flight phases:

thrust = bada3.Thrust("A320", bada_path)

# Maximum climb thrust
thrust.climb(tas=280, alt=20_000)  # kts, ft -> N

# Maximum cruise thrust (95% of climb thrust)
thrust.cruise(tas=450, alt=35_000)

# Takeoff thrust
thrust.takeoff(tas=150, alt=0)

# Idle (descent) thrust - requires configuration
thrust.idle(tas=300, alt=25_000, config="CR")  # cruise descent
thrust.idle(tas=200, alt=5_000, config="AP")   # approach
thrust.idle(tas=150, alt=1_000, config="LD")   # landing

The config parameter for idle thrust:

  • "CR" - Cruise/clean configuration
  • "AP" - Approach configuration
  • "LD" - Landing configuration

8.1.4 Fuel Flow

fuel = bada3.FuelFlow("A320", bada_path)

# Enroute fuel flow (cruise, corrected)
fuel.enroute(mass=60000, tas=450, alt=35_000)  # kg, kts, ft -> kg/s

# Nominal fuel flow (before cruise correction)
fuel.nominal(mass=60000, tas=450, alt=35_000, vs=0)

# Idle fuel flow
fuel.idle(mass=60000, tas=300, alt=25_000)

# Approach/landing fuel flow
fuel.approach(mass=60000, tas=150, alt=3_000)

8.1.5 ISA Temperature Deviation

All thrust and fuel calculations support ISA temperature deviation using the dT parameter:

# Hot day scenario (+15K above ISA)
thrust.climb(tas=280, alt=20_000, dT=15)
fuel.enroute(mass=60000, tas=450, alt=35_000, vs=500, dT=15)

8.2 BADA4

BADA4 uses a more sophisticated polynomial model with higher fidelity, especially for modern aircraft. The data is stored in XML format.

8.2.1 Setup

from openap.addon import bada4

bada_path = "path/to/bada_4.x/tables"

8.2.2 Drag

drag = bada4.Drag("A320", bada_path)

drag.clean(mass=60000, tas=300, alt=35_000)  # kg, kts, ft -> N

The aircraft type can be ICAO typecode like A320 or with subtypes like A320-231.

8.2.3 Thrust

thrust = bada4.Thrust("A320", bada_path)

# Maximum climb thrust (MCMB rating)
thrust.climb(tas=280, alt=20_000)

# Maximum cruise thrust (MCRZ rating)
thrust.cruise(tas=450, alt=35_000)

# Takeoff thrust
thrust.takeoff(tas=150, alt=0)

# Idle thrust (LIDL rating)
thrust.idle(tas=300, alt=25_000)

8.2.4 Fuel Flow

fuel = bada4.FuelFlow("A320", bada_path)

# Enroute fuel flow
fuel.enroute(mass=60000, tas=450, alt=35_000)  # kg, kts, ft -> kg/s

# Idle fuel flow
fuel.idle(mass=60000, tas=300, alt=25_000)

The enroute method automatically switches to idle fuel flow when vertical speed is below -250 ft/min.

8.3 Vectorized Calculations

Tip

All BADA models support vectorized calculations. Input parameters can be provided as lists or numpy arrays for fast batch processing.

In the following example, we show how to calculate the fuel flow from a flight data file obtained from opensky state vectors. First, we read the data file and calculate the time step between each row.

import pandas as pd
import openap
from openap.addon import bada4

typecode = "A319"
fuel_bada = bada4.FuelFlow(typecode, bada_path)

df = pd.read_csv("path/to/your/fightdata.csv")
dt = df.timestamp.diff().bfill().dt.total_seconds()  # time step in seconds

# assume 85% of MTOW as initial mass
mass0 = openap.prop.aircraft(typecode)["mtow"] * 0.85

Then we calculate the fuel flow at each time step and sum the total fuel consumed.

# first pass to get an initial guess with reference mass
fuel_flow_initial_guess = fuel_bada.enroute(
    mass=mass0,
    tas=df.groundspeed,
    alt=df.altitude,
    vs=df.vertical_rate,
).flatten()

# correct the mass at each time step
mass = mass0 - (fuel_flow_initial_guess * dt).cumsum()

# second pass with corrected mass
fuel_flow = fuel_bada.enroute(
    mass=mass, tas=df.groundspeed, alt=df.altitude, vs=df.vertical_rate
).flatten()

total_fuel = sum(fuel_flow * dt)

The cacluation takes approximately 4.6 ms Β± 33.7 ΞΌs for a flight dataframe with ~ 7,000 rows on aRyzen 7 7840HS CPU.