Files
aman-sys/aman/sys/WeatherModel.py
2021-10-13 12:52:29 +02:00

149 lines
4.6 KiB
Python

#!/usr/bin/env python
from aman.com.Weather import Weather
import math
import scipy.interpolate
class WeatherModel:
def __init__(self, gaforId, weather : Weather):
self.Gafor = gaforId
self.Weather = weather
self.WindDirectionModel = None
self.WindSpeedModel = None
self.LastWeatherUpdate = None
self.MinimumAltitude = 1000000
self.MaximumAltitude = -1
# create the density interpolation model
# the density model is based on https://aerotoolbox.com/atmcalc/
altitudes = [
50000,
45000,
40000,
38000,
36000,
34000,
32000,
30000,
28000,
26000,
24000,
22000,
20000,
18000,
16000,
15000,
14000,
13000,
12000,
11000,
10000,
9000,
8000,
7000,
6000,
5000,
4000,
3000,
2000,
1000,
0
]
densities = [
0.18648,
0.23714,
0.24617,
0.33199,
0.36518,
0.39444,
0.42546,
0.45831,
0.402506,
0.432497,
0.464169,
0.60954,
0.65269,
0.69815,
0.74598,
0.77082,
0.79628,
0.82238,
0.84914,
0.87655,
0.90464,
0.93341,
0.96287,
0.99304,
1.02393,
1.05555,
1.08791,
1.12102,
1.1549,
1.18955,
1.225
]
self.densityModel = scipy.interpolate.interp1d(altitudes, densities)
def calculateTAS(self, altitude : int, ias : int):
if altitude >= 50000:
altitude = 49999
if altitude <= 0:
altitude = 1
# calculation based on https://aerotoolbox.com/airspeed-conversions/
return ias * math.sqrt(1.225 / self.densityModel(altitude).item())
def updateWindModel(self):
if None == self.LastWeatherUpdate or self.LastWeatherUpdate != self.Weather.Provider.UpdateTime:
self.LastWeatherUpdate = self.Weather.Provider.UpdateTime
self.MinimumAltitude = 1000000
self.MaximumAltitude = -1
self.WindDirectionModel = None
self.WindSpeedModel = None
if None != self.Weather.Provider.WindData and self.Gafor in self.Weather.Provider.WindData:
altitudes = []
directions = []
speeds = []
# collect the data for the wind model
for level in self.Weather.Provider.WindData[self.Gafor]:
altitudes.append(level[0])
directions.append(level[1])
speeds.append(level[2])
# define the thresholds for later boundary checks
if self.MinimumAltitude > level[0]:
self.MinimumAltitude = level[0]
if self.MaximumAltitude < level[0]:
self.MaximumAltitude = level[0]
# calculate the models
if 1 < len(altitudes):
self.WindDirectionModel = scipy.interpolate.interp1d(altitudes, directions)
self.WindSpeedModel = scipy.interpolate.interp1d(altitudes, speeds)
def calculateGS(self, altitude : int, ias : int, heading : int):
self.updateWindModel()
tas = self.calculateTAS(altitude, ias)
# initialize the wind data
if None != self.WindDirectionModel and None != self.WindSpeedModel:
direction = 0.0
speed = 0.0
if None != self.WindSpeedModel and None != self.WindDirectionModel:
if self.MaximumAltitude <= altitude:
altitude = self.MaximumAltitude - 1
if self.MinimumAltitude >= altitude:
altitude = self.MinimumAltitude + 1
direction = self.WindDirectionModel(altitude).item()
speed = self.WindSpeedModel(altitude).item()
else:
speed = 0
direction = 0
# calculate the ground speed based on the headwind component
return tas + speed * math.cos(math.radians(direction) - math.radians(heading))