kopia lustrzana https://github.com/glidernet/python-ogn-client
Added optionally distance calculation (fixes #86)
rodzic
8855a4f097
commit
4a9a884d7c
|
@ -1,5 +1,6 @@
|
||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
## not released
|
## not released
|
||||||
|
- parser: Added optionally distance calculation (fixes #86)
|
||||||
- parser: Added support for weather data from FANET ground stations
|
- parser: Added support for weather data from FANET ground stations
|
||||||
- parser: Added support for latency in receiver messages (OGNSDR) (fixes #87)
|
- parser: Added support for latency in receiver messages (OGNSDR) (fixes #87)
|
||||||
- parser: Added support for reference_timestamp with tzinfo (fixes #84)
|
- parser: Added support for reference_timestamp with tzinfo (fixes #84)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import re
|
import re
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from ogn.parser.utils import createTimestamp, parseAngle, KNOTS_TO_MS, KPH_TO_MS, FEETS_TO_METER, fahrenheit_to_celsius
|
from ogn.parser.utils import createTimestamp, parseAngle, KNOTS_TO_MS, KPH_TO_MS, FEETS_TO_METER, fahrenheit_to_celsius, CheapRuler
|
||||||
from ogn.parser.pattern import PATTERN_APRS, PATTERN_APRS_POSITION, PATTERN_APRS_POSITION_WEATHER, PATTERN_APRS_STATUS, PATTERN_SERVER
|
from ogn.parser.pattern import PATTERN_APRS, PATTERN_APRS_POSITION, PATTERN_APRS_POSITION_WEATHER, PATTERN_APRS_STATUS, PATTERN_SERVER
|
||||||
from ogn.parser.exceptions import AprsParseError
|
from ogn.parser.exceptions import AprsParseError
|
||||||
|
|
||||||
|
@ -18,8 +18,12 @@ from ogn.parser.aprs_comment.spot_parser import SpotParser
|
||||||
from ogn.parser.aprs_comment.inreach_parser import InreachParser
|
from ogn.parser.aprs_comment.inreach_parser import InreachParser
|
||||||
from ogn.parser.aprs_comment.generic_parser import GenericParser
|
from ogn.parser.aprs_comment.generic_parser import GenericParser
|
||||||
|
|
||||||
|
positions = {}
|
||||||
|
|
||||||
|
|
||||||
|
def parse(aprs_message, reference_timestamp=None, calculate_distances=False):
|
||||||
|
global positions
|
||||||
|
|
||||||
def parse(aprs_message, reference_timestamp=None):
|
|
||||||
if reference_timestamp is None:
|
if reference_timestamp is None:
|
||||||
reference_timestamp = datetime.utcnow()
|
reference_timestamp = datetime.utcnow()
|
||||||
|
|
||||||
|
@ -28,6 +32,13 @@ def parse(aprs_message, reference_timestamp=None):
|
||||||
message.update(parse_comment(message['comment'],
|
message.update(parse_comment(message['comment'],
|
||||||
dstcall=message['dstcall'],
|
dstcall=message['dstcall'],
|
||||||
aprs_type=message['aprs_type']))
|
aprs_type=message['aprs_type']))
|
||||||
|
|
||||||
|
if message['aprs_type'].startswith('position') and calculate_distances is True:
|
||||||
|
positions[message['name']] = (message['longitude'], message['latitude'])
|
||||||
|
if message['receiver_name'] in positions:
|
||||||
|
cheap_ruler = CheapRuler((message['latitude'] + positions[message['receiver_name']][1]) / 2.0)
|
||||||
|
message['distance'] = cheap_ruler.distance((message['longitude'], message['latitude']), positions[message['receiver_name']])
|
||||||
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
|
import math
|
||||||
|
|
||||||
FEETS_TO_METER = 0.3048 # ratio feets to meter
|
FEETS_TO_METER = 0.3048 # ratio feets to meter
|
||||||
FPM_TO_MS = FEETS_TO_METER / 60 # ratio fpm to m/s
|
FPM_TO_MS = FEETS_TO_METER / 60 # ratio fpm to m/s
|
||||||
|
@ -52,3 +53,24 @@ def createTimestamp(time_string, reference_timestamp):
|
||||||
result += timedelta(days=1)
|
result += timedelta(days=1)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class CheapRuler():
|
||||||
|
"""Extreme fast distance calculating for distances below 500km."""
|
||||||
|
|
||||||
|
def __init__(self, lat):
|
||||||
|
c = math.cos(lat * 3.14159265359 / 180)
|
||||||
|
c2 = 2 * c * c - 1
|
||||||
|
c3 = 2 * c * c2 - c
|
||||||
|
c4 = 2 * c * c3 - c2
|
||||||
|
c5 = 2 * c * c4 - c3
|
||||||
|
|
||||||
|
self.kx = 1000 * (111.41513 * c - 0.09455 * c3 + 0.00012 * c5) # longitude correction
|
||||||
|
self.ky = 1000 * (111.13209 - 0.56605 * c2 + 0.0012 * c4) # latitude correction
|
||||||
|
|
||||||
|
def distance(self, a, b):
|
||||||
|
"""Points a and b are from tuple(lon,lat)."""
|
||||||
|
|
||||||
|
dx = (a[0] - b[0]) * self.kx
|
||||||
|
dy = (a[1] - b[1]) * self.ky
|
||||||
|
return math.sqrt(dx * dx + dy * dy)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import unittest
|
import unittest
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
from ogn.parser.utils import parseAngle, createTimestamp
|
from ogn.parser.utils import parseAngle, createTimestamp, CheapRuler
|
||||||
|
|
||||||
|
|
||||||
class TestStringMethods(unittest.TestCase):
|
class TestStringMethods(unittest.TestCase):
|
||||||
|
@ -40,6 +40,14 @@ class TestStringMethods(unittest.TestCase):
|
||||||
|
|
||||||
self.proceed_test_data(test_data)
|
self.proceed_test_data(test_data)
|
||||||
|
|
||||||
|
def test_cheap_ruler(self):
|
||||||
|
koenigsdf = (11.465353, 47.829825)
|
||||||
|
hochkoenig = (13.062405, 47.420516)
|
||||||
|
|
||||||
|
cheap_ruler = CheapRuler((koenigsdf[1] + hochkoenig[1]) / 2)
|
||||||
|
distance = cheap_ruler.distance(koenigsdf, hochkoenig)
|
||||||
|
self.assertEqual(distance, 128381.47612138899)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
Ładowanie…
Reference in New Issue