diff --git a/ogn/commands/dbutils.py b/ogn/commands/dbutils.py index be2d294..070d7fc 100644 --- a/ogn/commands/dbutils.py +++ b/ogn/commands/dbutils.py @@ -1,8 +1,13 @@ import os import importlib -from sqlalchemy import create_engine + +from sqlalchemy import create_engine, and_, desc +from sqlalchemy.sql import null from sqlalchemy.orm import sessionmaker +from ogn.model import AircraftBeacon, ReceiverBeacon +from ogn.utils import wgs84_to_sphere + os.environ.setdefault('OGN_CONFIG_MODULE', 'config.default') @@ -11,3 +16,26 @@ engine = create_engine(config.SQLALCHEMY_DATABASE_URI, echo=False) Session = sessionmaker(bind=engine) session = Session() + + +def update_receiver_childs(name): + last_receiver_beacon = session.query(ReceiverBeacon) \ + .filter(ReceiverBeacon.name == name) \ + .order_by(desc(ReceiverBeacon.timestamp)) \ + .first() + + if (last_receiver_beacon is None): + return + + aircraft_beacons_query = session.query(AircraftBeacon) \ + .filter(and_(AircraftBeacon.timestamp > last_receiver_beacon.timestamp, + AircraftBeacon.receiver_name == name, + AircraftBeacon.radius == null())) + + for aircraft_beacon in aircraft_beacons_query.all(): + [radius, theta, phi] = wgs84_to_sphere(last_receiver_beacon, + aircraft_beacon) + aircraft_beacon.radius = radius + aircraft_beacon.theta = theta + aircraft_beacon.phi = phi + session.commit() diff --git a/ogn/gateway/manage.py b/ogn/gateway/manage.py index d7ce903..063cd17 100644 --- a/ogn/gateway/manage.py +++ b/ogn/gateway/manage.py @@ -1,9 +1,11 @@ import logging from ogn.gateway.client import ognGateway -from ogn.commands.dbutils import session +from ogn.commands.dbutils import session, update_receiver_childs +from ogn.model import ReceiverBeacon from manager import Manager + manager = Manager() logging_formatstr = '%(asctime)s - %(levelname).4s - %(name)s - %(message)s' @@ -33,6 +35,8 @@ def run(aprs_user='anon-dev', logfile='main.log', loglevel='INFO'): gateway.connect() def process_beacon(beacon): + if isinstance(beacon, ReceiverBeacon): + update_receiver_childs(beacon.name) session.add(beacon) session.commit() diff --git a/ogn/utils.py b/ogn/utils.py index e1219aa..698ef68 100644 --- a/ogn/utils.py +++ b/ogn/utils.py @@ -60,3 +60,24 @@ def get_country_code(latitude, longitude): except KeyError: country_code = None return country_code + + +def wgs84_to_sphere(receiver_beacon, aircraft_beacon): + from math import pi, asin, sqrt, sin, cos, atan2 + deg2rad = pi / 180 + rad2deg = 180 / pi + + lat1 = receiver_beacon.latitude * deg2rad + lon1 = receiver_beacon.longitude * deg2rad + alt1 = receiver_beacon.altitude + + lat2 = aircraft_beacon.latitude * deg2rad + lon2 = aircraft_beacon.longitude * deg2rad + alt2 = aircraft_beacon.altitude + + distance = 6366000 * 2 * asin(sqrt((sin((lat1 - lat2) / 2))**2 + cos(lat1) * cos(lat2) * (sin((lon1 - lon2) / 2))**2)) + theta = atan2(alt2 - alt1, distance) * rad2deg + phi = atan2(sin(lon1 - lon2) * cos(lat2), cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon1 - lon2)) * rad2deg + + radius = sqrt(distance**2 + (alt2 - alt1)**2) + return radius, theta, phi diff --git a/tests/test_utils.py b/tests/test_utils.py index 8b2d03c..8a18173 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,7 +1,7 @@ import unittest -from ogn.utils import get_ddb, get_trackable, get_country_code -from ogn.model import AddressOrigin +from ogn.utils import get_ddb, get_trackable, get_country_code, wgs84_to_sphere +from ogn.model import AddressOrigin, Beacon class TestStringMethods(unittest.TestCase): @@ -43,3 +43,52 @@ class TestStringMethods(unittest.TestCase): longitude = -0.0009119 country_code = get_country_code(latitude, longitude) self.assertEqual(country_code, None) + + def test_wgs84_to_sphere(self): + receiver_beacon = Beacon() + receiver_beacon.latitude = 0 + receiver_beacon.longitude = 0 + receiver_beacon.altitude = 0 + + # delta: one latitude degree + aircraft_beacon = Beacon() + aircraft_beacon.latitude = -1 + aircraft_beacon.longitude = 0 + aircraft_beacon.altitude = 0 + [radius, theta, phi] = wgs84_to_sphere(receiver_beacon, aircraft_beacon) + self.assertAlmostEqual(radius, 60 * 1852, -2) + self.assertEqual(theta, 0) + self.assertEqual(phi, 180) + + # delta: one longitude degree at the equator + aircraft_beacon.latitude = 0 + aircraft_beacon.longitude = -1 + aircraft_beacon.altitude = 0 + [radius, theta, phi] = wgs84_to_sphere(receiver_beacon, aircraft_beacon) + self.assertAlmostEqual(radius, 60 * 1852, -2) + self.assertEqual(theta, 0) + self.assertEqual(phi, 90) + + # delta: 1000m altitude + aircraft_beacon.latitude = 0 + aircraft_beacon.longitude = 0 + aircraft_beacon.altitude = 1000 + [radius, theta, phi] = wgs84_to_sphere(receiver_beacon, aircraft_beacon) + self.assertAlmostEqual(radius, 1000, 3) + self.assertEqual(theta, 90) + self.assertEqual(phi, 0) + + # receiver + receiver_beacon.latitude = 48.865 + receiver_beacon.longitude = 9.2225 + receiver_beacon.altitude = 574 + + # aircraft beacon + aircraft_beacon.latitude = 48.74435 + aircraft_beacon.longitude = 9.578 + aircraft_beacon.altitude = 929 + + [radius, theta, phi] = wgs84_to_sphere(receiver_beacon, aircraft_beacon) + self.assertAlmostEqual(radius, 29265.6035812215, -1) + self.assertAlmostEqual(theta, 0.694979846308314, 5) + self.assertAlmostEqual(phi, -117.1275408121, 5)