Compare commits

...

10 Commits

Author SHA1 Message Date
Sven Czarnian
a1c48d7851 Merge branch 'feature/weather' into 'develop'
Feature/weather

See merge request nav/aman/aman-sys!2
2021-10-12 20:11:47 +00:00
Sven Czarnian
a86dfa01d8 add a weather model 2021-10-11 21:58:14 +02:00
Sven Czarnian
c6d22d2067 fix the protobuffer version 2021-10-11 21:57:47 +02:00
Sven Czarnian
23add20513 remove wrong imports 2021-10-11 21:57:09 +02:00
Sven Czarnian
fd324ea747 add some logging 2021-10-11 21:56:51 +02:00
Sven Czarnian
ebea408267 make the datetime code more readable 2021-10-11 21:56:39 +02:00
Sven Czarnian
8b43991c50 remove unreachable code 2021-10-10 08:27:19 +02:00
Sven Czarnian
11eae85e35 remove useless checks 2021-10-10 08:27:10 +02:00
Sven Czarnian
7e17bf0103 removed unused files 2021-10-10 08:26:49 +02:00
Sven Czarnian
667829b03d fix a crash during the update call 2021-09-25 09:03:55 +02:00
11 changed files with 168 additions and 93 deletions

View File

@@ -1,18 +0,0 @@
# RHC-ACS-ASS Algorithm
# This class is written to contain an implementation
# of the Ant Colony System based upon the Receding Horizon
# for Aircraft Arrival Sequencing
class RhcAcsAss:
k = 1 # Receding horizon counter
N_rhc = 4 # The number of receding horizons
T_ti = 1 # The scheduling window
def __init__(self, n, t):
self.N_rhc = n
self.T_ti = t
def find_aircraft_for_horizon(self, ki):
# Omega(k) = [(k-1) * T_ti, (k+N_rhc-1) * T_ti]
pass

View File

@@ -91,8 +91,7 @@ class AMAN:
# find the correct worker for the inbound
for worker in self.workers:
if worker.icao == report.destination:
print('Updated ' + report.aircraft.callsign + ' for ' + worker.icao)
worker.acquire()
worker.acquireLock()
worker.reportQueue[report.aircraft.callsign] = report
worker.release()
worker.releaseLock()
break

View File

@@ -1,2 +0,0 @@
import com
import tools

View File

@@ -155,5 +155,3 @@ class DwdCrawler():
return True
else:
return False
return False

View File

@@ -1,6 +1,5 @@
#!/usr/bin/env python
import datetime
import pytz
import sys
import time
@@ -39,16 +38,7 @@ class Weather(Thread):
self.join()
def currentClock():
clock = dt.utcfromtimestamp(int(time.time()))
clock = datetime.datetime(
year = clock.year,
month = clock.month,
day = clock.day,
hour = clock.hour,
minute = clock.minute,
second = clock.second,
tzinfo = pytz.UTC
)
clock = dt.utcfromtimestamp(int(time.time())).replace(tzinfo = pytz.UTC)
return clock
def run(self):
@@ -60,10 +50,7 @@ class Weather(Thread):
time.sleep(1)
continue
# calculate the theoretical next try for an update
if None != self.lastUpdateTried:
earliestUpdate = self.lastUpdateTried + datetime.timedelta(minutes=2)
if None == self.lastUpdateTried or self.lastUpdateTried <= now:
if True == self.provider.receiveWindData():
self.nextUpdate = self.provider.updateTime
self.nextUpdate = self.provider.updateTime
print('Received new wind data')

148
aman/sys/WeatherModel.py Normal file
View File

@@ -0,0 +1,148 @@
#!/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))

View File

@@ -8,6 +8,12 @@ from aman.config.Airport import Airport
class Worker(Thread):
def __init__(self):
Thread.__init__(self)
self.stopThread = None
self.icao = None
self.configuration = None
self.arrivalRoutes = None
self.updateLock = None
self.reportQueue = {}
def __del__(self):
self.release()
@@ -21,10 +27,18 @@ class Worker(Thread):
self.reportQueue = {}
self.start()
def acquireLock(self):
if None != self.updateLock:
self.updateLock.acquire()
def release(self):
self.stopThread = True
self.join()
def releaseLock(self):
if None != self.updateLock:
self.updateLock.release()
def run(self):
counter = 0

Binary file not shown.

View File

@@ -1,51 +0,0 @@
import socket
import _thread
class TCPServer(socket.socket):
clients = []
def __init__(self):
socket.socket.__init__(self)
self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.bind(('0.0.0.0', 8765))
self.listen(5)
def run(self):
print("Starting TCP Server")
try:
self.accept_clients()
except Exception as ex:
print(ex)
finally:
print("Server shutdown")
for client in self.clients:
client.close()
self.close()
def accept_clients(self):
while True:
(client_socket, address) = self.accept()
self.clients.append(client_socket)
self.on_open(client_socket)
_thread.start_new_thread(self.receive, (client_socket,))
def receive(self, client):
while True:
data = client.recv(1024)
if data == '':
break
self.on_message(client, data)
self.clients.remove(client)
self.on_close(client)
client.close()
_thread.exit()
def on_open(self, client):
pass
def on_message(self, client, message):
pass
def on_close(self, client):
pass