Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions bluebird-dt/bluebird_dt/core/aircraft.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ def __init__(
Upon instantiation this is set to the current flight level.
Note that if a flight level is given that is not a multiple of 10, it will be rounded to the nearest
multiple of 10.
speed_cas: float or None
The calibrated airspeed (CAS) of the Aircraft in knots.
speed_tas: float or None
The true airspeed (TAS) of the Aircraft in knots.
This is only set by the Predictors.
Expand Down Expand Up @@ -373,6 +375,7 @@ def __init__(
self.selected_instructions = Instructions(fl=use_fl, on_route=True)

self.vertical_speed: float = 0.0
self.speed_cas: float | None = None
self.speed_tas: float | None = None
self.ground_speed: float | None = None

Expand Down Expand Up @@ -640,6 +643,7 @@ def from_json(cls, s: str) -> typing_extensions.Self:
)

# attributes
aircraft.speed_cas = data.get("speed_cas", None)
aircraft.speed_tas = data.get("speed_tas", None)
aircraft.ground_speed = data.get("ground_speed", None)
aircraft.ground_track_angle = data.get("ground_track_angle", None)
Expand Down Expand Up @@ -727,6 +731,7 @@ def data(self) -> dict[str, typing.Any]:
"squawk": self.squawk,
"squawk_ident_until": self.squawk_ident_until,
"wake_vortex": self.wake_vortex,
"speed_cas": self.speed_cas,
"speed_tas": self.speed_tas,
"vertical_speed": self.vertical_speed,
"ground_speed": self.ground_speed,
Expand Down
3 changes: 2 additions & 1 deletion bluebird-dt/bluebird_dt/events/event_dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class EventDtypes:

# specify expected datatypes for each EventHandler dataframe
radar_dtypes: ClassVar[dict[str, str]] = {
# ufid, speed_tas, ground_speed, ground_track angle and selected_fl
# ufid, speed_cas, speed_tas, ground_speed, ground_track angle and selected_fl
# are all optional columns and values and will be added automatically
# if required
"datetime": "datetime64[us]", # datetime in utc
Expand All @@ -16,6 +16,7 @@ class EventDtypes:
"fl": "float64",
"heading": "float64",
"ufid": "category", # optional
"speed_cas": "float64", # optional
"speed_tas": "float64", # optional
"ground_speed": "float64", # optional
"ground_track_angle": "float64", # optional
Expand Down
11 changes: 10 additions & 1 deletion bluebird-dt/bluebird_dt/events/event_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

import numpy as np
import pandas as pd
from pydantic import BaseModel
import typing_extensions
from pydantic import BaseModel
from typing_extensions import Self

from bluebird_dt.core import (
Expand Down Expand Up @@ -262,6 +262,7 @@ def add_optional_radar_columns_if_required(self) -> None:
columns = self.radar_df.columns

optional_float_cols = [
"speed_cas",
"speed_tas",
"ground_speed",
"ground_track_angle",
Expand Down Expand Up @@ -401,6 +402,7 @@ def add_aircraft(self, the_datetime: datetime, aircraft: Aircraft):
fl=aircraft.fl,
heading=aircraft.heading,
ufid=aircraft.ufid,
speed_cas=aircraft.speed_cas,
speed_tas=aircraft.speed_tas,
ground_speed=aircraft.ground_speed,
ground_track_angle=aircraft.ground_track_angle,
Expand Down Expand Up @@ -537,6 +539,7 @@ def add_radar_event(
fl: float,
heading: float,
ufid: str | None = None,
speed_cas: float | None = None,
speed_tas: float | None = None,
ground_speed: float | None = None,
ground_track_angle: float | None = None,
Expand All @@ -561,6 +564,8 @@ def add_radar_event(
Heading of aircraft
ufid: str, optional
Unique Flight ID of aircraft
speed_cas: float, optional
Calibrated Airspeed of the aircraft
speed_tas: float, optional
True Airspeed of the aircraft
ground_speed: float, optional
Expand All @@ -577,6 +582,7 @@ def add_radar_event(
"fl": fl,
"heading": heading,
"ufid": ufid,
"speed_cas": speed_cas,
"speed_tas": speed_tas,
"ground_speed": ground_speed,
"ground_track_angle": ground_track_angle,
Expand Down Expand Up @@ -1637,6 +1643,9 @@ def update_from_radar(
# calculate the tas
aircraft.speed_tas = tas_from_ground_speed(aircraft.ground_speed, aircraft.ground_track_angle, wind_vector)

if row.speed_cas is not None:
aircraft.speed_cas = row.speed_cas

if row.heading is not None:
aircraft.heading = row.heading

Expand Down
5 changes: 5 additions & 0 deletions bluebird-dt/bluebird_dt/predictor/linear_predictor.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
cas_to_tas,
mach_cas_trans_altitude,
mach_to_tas,
tas_to_cas,
)
from bluebird_dt.utility.paths import (
AIRCRAFT_WEIGHT_MAPPING_FILE,
Expand Down Expand Up @@ -234,6 +235,9 @@ def update_total_speeds(self, aircraft: Aircraft):
# Set the aircraft TAS
aircraft.speed_tas = tas_KT

# Set the aircraft CAS
aircraft.speed_cas = tas_to_cas(aircraft.fl, aircraft.speed_tas * KT_TO_MPS, self.delta_T) * MPS_TO_KT

def update_total_speeds_cas_is_tas(self, aircraft: Aircraft):
"""
Updates total speeds of a selected aircraft by writing the selected_instructions.cas value directly to the true
Expand All @@ -251,6 +255,7 @@ def update_total_speeds_cas_is_tas(self, aircraft: Aircraft):
raise ValueError("Aircraft.selected_instructions.cas must be set to use cas_is_tas speed modelling.")

aircraft.speed_tas = cas
aircraft.speed_cas = cas

@functools.lru_cache
def _get_performance_profile(self, key: str | None) -> dict[str, list[float | None] | float]:
Expand Down
11 changes: 7 additions & 4 deletions bluebird-dt/bluebird_dt/predictor/simple_predictor.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ def update_speeds(self, aircraft: Aircraft, wind_field: WindField | None):
def update_total_speeds_cas_is_tas(self, aircraft: Aircraft):
"""
Updates total speeds of a selected aircraft by writing the selected_instructions.cas value directly to the true
airspeed (speed_tas) value. Mach values are ignored. This method is called when the flag "use_cas_as_tas" is set
to True. If the selected_instructions.cas value is None, then an error is raised: this must be set to use this
simplified speed modelling.
airspeed (speed_tas) and calibrated airspeed (speed_cas) values. Mach values are ignored. This method is called
when the flag "use_cas_as_tas" is set to True. If the selected_instructions.cas value is None, then an error is
raised: this must be set to use this simplified speed modelling.

Parameters
----------
Expand All @@ -162,7 +162,10 @@ def update_total_speeds_cas_is_tas(self, aircraft: Aircraft):
if aircraft.selected_instructions.cas is None:
raise ValueError("Aircraft.selected_instructions.cas must be set to use cas_is_tas speed modelling.")

aircraft.speed_tas = aircraft.selected_instructions.cas
cas = aircraft.selected_instructions.cas

aircraft.speed_tas = cas
aircraft.speed_cas = cas

def update_vertical_speeds(self, aircraft: Aircraft):
"""
Expand Down
1 change: 1 addition & 0 deletions bluebird-dt/bluebird_dt/simulator/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@ def dynamic_data(
"heading": aircraft.heading,
"ground_track": aircraft.ground_track_angle,
"cleared_heading": aircraft.cleared_instructions.heading,
"calibrated_air_speed": aircraft.speed_cas,
"true_air_speed": aircraft.speed_tas,
"ground_speed": aircraft.ground_speed,
"filed_true_airspeed": filed_true_airspeed,
Expand Down
4 changes: 2 additions & 2 deletions bluebird-dt/bluebird_dt/utility/paths.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import importlib.resources
import os
from pathlib import Path

ROOT_DIR = importlib.resources.files("bluebird_dt")
ROOT_DIR = Path(__file__).resolve().parent.parent
# We have the data in the bluebird_dt package itself.
BASE_DATA_DIR = ROOT_DIR.joinpath("scenario_data")
LOG_DIR: str = os.path.join(BASE_DATA_DIR, "scenario_logs")
Expand Down
1 change: 1 addition & 0 deletions bluebird-dt/tests/unit/core/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ def make_random_aircraft(callsign: str | None = None) -> Aircraft:
squawk_ident_until=squawk_ident_until,
)

aircraft.speed_cas = cleared_cas
aircraft.speed_tas = cleared_cas # based on what happens in linear predictor
aircraft.vertical_speed = vertical_speed
aircraft.heading_changing_to = heading_changing_to
Expand Down
2 changes: 2 additions & 0 deletions bluebird-dt/tests/unit/core/test_aircraft.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ def test_data():
assert data["cleared_instructions"]["cas"] is None
assert data["cleared_instructions"]["mach"] is None
assert data["cleared_instructions"]["vertical_speed"] is None
assert data["speed_cas"] is None
assert data["speed_tas"] is None
assert data["vertical_speed"] == pytest.approx(0.0)
assert data["ground_speed"] is None
Expand Down Expand Up @@ -173,6 +174,7 @@ def test_data():
assert data["selected_instructions"]["mach"] == cleared_mach
assert data["selected_instructions"]["vertical_speed"] == cleared_vertical_speed
assert data["selected_instructions"]["on_route"] == on_route
assert data["speed_cas"] is None
assert data["speed_tas"] is None
assert data["vertical_speed"] == vertical_speed
assert data["ground_speed"] is None
Expand Down
Loading