diff --git a/api/map/event/radar.js b/api/map/event/radar.js
index f9e7d82..453f95c 100644
--- a/api/map/event/radar.js
+++ b/api/map/event/radar.js
@@ -1,4 +1,26 @@
function event_radar() {
- setTimeout(event_radar, 1000);
+ radar_url = window.location.origin + '/api' + window.location.search;
+ console.log(radar_url);
+
+ fetch(radar_url)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then(data => {
+ // Update aircraft points based on new data
+ console.log("test");
+ })
+ .catch(error => {
+ // Handle errors during fetch
+ console.error('Error during fetch:', error);
+ })
+ .finally(() => {
+ // Schedule the next fetch after a delay (e.g., 5 seconds)
+ setTimeout(event_radar, 1000);
+ });
+
}
\ No newline at end of file
diff --git a/api/templates/map.html b/api/templates/map.html
deleted file mode 100644
index 98f95e1..0000000
--- a/api/templates/map.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
- Map Page
-
-
- Map Page
-
-
-
diff --git a/common/Message.py b/common/Message.py
index 1f36d87..5e9f748 100644
--- a/common/Message.py
+++ b/common/Message.py
@@ -58,7 +58,7 @@ class Message:
with conn:
while True:
- data = conn.recv(1024)
+ data = conn.recv(65000)
if not data:
break
decoded_data = data.decode()
@@ -82,7 +82,7 @@ class Message:
try:
client_socket.connect((self.host, self.port))
client_socket.sendall(message.encode())
- reply = client_socket.recv(1024).decode()
+ reply = client_socket.recv(65000).decode()
return reply
except ConnectionRefusedError:
print(f"Connection to {self.host}:{self.port} refused.")
diff --git a/event/algorithm/associator/AdsbAssociator.py b/event/algorithm/associator/AdsbAssociator.py
index 65ac0cc..6ef7904 100644
--- a/event/algorithm/associator/AdsbAssociator.py
+++ b/event/algorithm/associator/AdsbAssociator.py
@@ -39,7 +39,10 @@ class AdsbAssociator:
for radar in radar_list:
- if radar_data[radar]["config"] is not None:
+ valid_config = radar_data[radar]["config"] is not None
+ valid_detection = radar_data[radar]["detection"] is not None
+
+ if valid_config and valid_detection:
# get URL for adsb2truth
url = self.generate_api_url(radar, radar_data[radar])
@@ -127,10 +130,7 @@ class AdsbAssociator:
tx_alt = radar_data['config']['location']['tx']['altitude']
fc = radar_data['config']['capture']['fc']
- if (radar == "radar5.30hours.dev"):
- adsb = radar_data['config']['truth']['adsb']['ip']
- else:
- adsb = radar_data['config']['truth']['adsb']['tar1090']
+ adsb = radar_data['config']['truth']['adsb']['tar1090']
api_url = "http://adsb2dd.30hours.dev/api/dd"
diff --git a/event/algorithm/coordreg/EllipsoidParametric.py b/event/algorithm/coordreg/EllipsoidParametric.py
index ada052c..464afbc 100644
--- a/event/algorithm/coordreg/EllipsoidParametric.py
+++ b/event/algorithm/coordreg/EllipsoidParametric.py
@@ -4,6 +4,8 @@
"""
from data.Ellipsoid import Ellipsoid
+from algorithm.geometry.Geometry import Geometry
+import numpy as np
class EllipsoidParametric:
@@ -20,18 +22,96 @@ class EllipsoidParametric:
@brief Constructor for the EllipsoidParametric class.
"""
+ self.ellipsoids = []
+
def process(self, assoc_detections, radar_data):
"""
@brief Perform coord registration using the ellipsoid parametric method.
@details Generate a (non arc-length) parametric ellipsoid for each node.
- Find
- @param radar_detections (str): JSON of blah2 radar detections.
- @param adsb_detections (str): JSON of adsb2dd truth detections.
+ @param assoc_detections (dict): JSON of blah2 radar detections.
+ @param radar_data (dict): JSON of adsb2dd truth detections.
@return str: JSON of associated detections.
"""
output = {}
+ # return if no detections
+ if not assoc_detections:
+ return output
+
+ for target in assoc_detections:
+
+ print(target, flush=True)
+
+ for radar in assoc_detections[target]:
+
+ print(radar["radar"], flush=True)
+ print(radar["delay"], flush=True)
+
+ # create ellipsoid for radar
+ ellipsoid = next((
+ item for item in self.ellipsoids
+ if item.name == radar["radar"]), None)
+
+ if ellipsoid is None:
+ config = radar_data[radar["radar"]]["config"]
+ x_tx, y_tx, z_tx = Geometry.lla2ecef(
+ config['location']['tx']['latitude'],
+ config['location']['tx']['longitude'],
+ config['location']['tx']['altitude']
+ )
+ x_rx, y_rx, z_rx = Geometry.lla2ecef(
+ config['location']['rx']['latitude'],
+ config['location']['rx']['longitude'],
+ config['location']['rx']['altitude']
+ )
+ ellipsoid = Ellipsoid(
+ [x_tx, y_tx, z_tx],
+ [x_rx, y_rx, z_rx],
+ radar["radar"]
+ )
+
+ print(ellipsoid.yaw, flush=True)
+ print(ellipsoid.pitch, flush=True)
+
+ self.sample(ellipsoid, radar["delay"], 10000)
+
+ print("", flush=True)
+
return output
-
\ No newline at end of file
+
+ def sample(self, ellipsoid, bistatic_range, n):
+
+ """
+ @brief Generate a set of points for the ellipsoid.
+ @details No arc length parametrisation.
+ @param ellipsoid (Ellipsoid): The ellipsoid object to use.
+ @param bistatic_range (float): Bistatic range for ellipsoid.
+ @param n (int): Number of points to generate.
+ @return list: Samples with size [n, 3].
+ """
+
+ # rotation matrix
+ phi = ellipsoid.pitch
+ theta = ellipsoid.yaw
+ R = np.array([
+ [np.cos(phi)*np.cos(theta), -np.sin(phi)*np.cos(theta), np.sin(theta)],
+ [np.sin(phi), np.cos(phi), 0],
+ [-np.cos(phi)*np.sin(theta), np.sin(phi)*np.sin(theta), np.cos(theta)]
+ ])
+
+ # compute samples vectorised
+ a = (bistatic_range-ellipsoid.distance)/2
+ b = np.sqrt(a**2 - (ellipsoid.distance/2))
+ u_values = np.linspace(0, 2 * np.pi, n)
+ v_values = np.linspace(-np.pi/2, np.pi/2, n)
+ u, v = np.meshgrid(u_values, v_values, indexing='ij')
+ x = a * np.cos(u)
+ y = b * np.sin(u) * np.cos(v)
+ z = b * np.sin(u) * np.sin(v)
+ r = np.stack([x, y, z], axis=-1).reshape(-1, 3)
+
+ r_1 = np.dot(r, R) + ellipsoid.midpoint
+
+ return r_1.tolist()
\ No newline at end of file
diff --git a/event/algorithm/geometry/Geometry.py b/event/algorithm/geometry/Geometry.py
new file mode 100644
index 0000000..5855f32
--- /dev/null
+++ b/event/algorithm/geometry/Geometry.py
@@ -0,0 +1,42 @@
+"""
+@file Geometry.py
+@author 30hours
+"""
+
+import math
+import numpy as np
+
+class Geometry:
+
+ """
+ @class Geometry
+ @brief A class to store geometric functions.
+ """
+
+ def __init__(self, f1, f2, name):
+
+ """
+ @brief Constructor for the Ellipsoid class.
+ """
+
+ def lla2ecef(latitude, longitude, altitude):
+
+ # WGS84 constants
+ a = 6378137.0 # semi-major axis in meters
+ f = 1 / 298.257223563 # flattening
+
+ # Convert latitude and longitude to radians
+ lat_rad = math.radians(latitude)
+ lon_rad = math.radians(longitude)
+
+ # Calculate the auxiliary values
+ cos_lat = math.cos(lat_rad)
+ sin_lat = math.sin(lat_rad)
+ N = a / math.sqrt(1 - f * (2 - f) * sin_lat**2)
+
+ # Calculate ECEF coordinates
+ ecef_x = (N + altitude) * cos_lat * math.cos(lon_rad)
+ ecef_y = (N + altitude) * cos_lat * math.sin(lon_rad)
+ ecef_z = (N * (1 - f) + altitude) * sin_lat
+
+ return ecef_x, ecef_y, ecef_z
diff --git a/event/data/Ellipsoid.py b/event/data/Ellipsoid.py
index c9939f3..d7ebb7e 100644
--- a/event/data/Ellipsoid.py
+++ b/event/data/Ellipsoid.py
@@ -11,19 +11,22 @@ class Ellipsoid:
@class Ellipsoid
@brief A class to store ellipsoid parameters for bistatic radar.
@details Stores foci, midpoint, pitch, yaw and distance.
- Able to generate samples through public functions.
"""
def __init__(self, f1, f2, name):
"""
@brief Constructor for the Ellipsoid class.
+ @param f1 (list): [x, y, z] of foci 1 in ECEF.
+ @param f2 (list): [x, y, z] of foci 2 in ECEF.
+ @param name (str): Name to associate with shape.
"""
self.f1 = f1
self.f2 = f2
self.name = name
+ # dependent members
self.midpoint = [(f1[0]+f2[0])/2,
(f1[1]+f2[1])/2, (f1[2]+f2[2])/2]
vector = (f2[0]-f1[0], f2[1]-f1[1], f2[2]-f1[2])
@@ -34,19 +37,3 @@ class Ellipsoid:
(f2[0] - f1[0])**2 +
(f2[1] - f1[1])**2 +
(f2[2] - f1[2])**2)
-
- def process(self, bistatic_range):
-
- """
- @brief Perform coord registration using the ellipsoid parametric method.
- @details Generate a (non arc-length) parametric ellipsoid for each node.
- Find
- @param radar_detections (str): JSON of blah2 radar detections.
- @param adsb_detections (str): JSON of adsb2dd truth detections.
- @return str: JSON of associated detections.
- """
-
- output = {}
-
- return output
-
\ No newline at end of file
diff --git a/event/event.py b/event/event.py
index 3f77a09..a72fa63 100644
--- a/event/event.py
+++ b/event/event.py
@@ -17,6 +17,9 @@ from algorithm.associator.AdsbAssociator import AdsbAssociator
from algorithm.coordreg.EllipsoidParametric import EllipsoidParametric
from common.Message import Message
+from data.Ellipsoid import Ellipsoid
+from algorithm.geometry.Geometry import Geometry
+
# init event loop
api = []
@@ -101,7 +104,27 @@ async def event():
# processing
associated_dets = associator.process(item["server"], radar_dict_item)
localised_dets = coordreg.process(associated_dets, radar_dict_item)
-
+
+ # tmp test
+ localised_dets = {}
+ localised_dets["test"] = {}
+ x_tx, y_tx, z_tx = Geometry.lla2ecef(
+ radar_dict_item['radar4.30hours.dev']["config"]['location']['tx']['latitude'],
+ radar_dict_item['radar4.30hours.dev']["config"]['location']['tx']['longitude'],
+ radar_dict_item['radar4.30hours.dev']["config"]['location']['tx']['altitude']
+ )
+ x_rx, y_rx, z_rx = Geometry.lla2ecef(
+ radar_dict_item['radar4.30hours.dev']["config"]['location']['rx']['latitude'],
+ radar_dict_item['radar4.30hours.dev']["config"]['location']['rx']['longitude'],
+ radar_dict_item['radar4.30hours.dev']["config"]['location']['rx']['altitude']
+ )
+ ellipsoid = Ellipsoid(
+ [x_tx, y_tx, z_tx],
+ [x_rx, y_rx, z_rx],
+ 'radar4.30hours.dev'
+ )
+ localised_dets["test"]["points"] = ellipsoidParametric.sample(ellipsoid, 10000, 5)
+
# output data to API
item["detections_associated"] = associated_dets
item["detections_localised"] = localised_dets
@@ -154,6 +177,8 @@ async def callback_message_received(msg):
else:
api[-1][key] = value
api[-1]["timestamp"] = timestamp
+ if not isinstance(api[-1]["server"], list):
+ api[-1]["server"] = [api[-1]["server"]]
# json dump
output = json.dumps(api)