mirror of
https://github.com/30hours/3lips.git
synced 2024-11-08 12:25:42 +00:00
Plot points from radar rx/tx in cesium
This commit is contained in:
parent
aaab58d2ea
commit
abce360cca
3 changed files with 180 additions and 27 deletions
107
api/map/main.js
107
api/map/main.js
|
@ -133,3 +133,110 @@ var viewer = new Cesium.Viewer("cesiumContainer", {
|
||||||
selectionIndicator: false
|
selectionIndicator: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a point to Cesium viewer with specified parameters.
|
||||||
|
* @param {number} latitude - The latitude of the point in degrees.
|
||||||
|
* @param {number} longitude - The longitude of the point in degrees.
|
||||||
|
* @param {number} altitude - The altitude of the point in meters.
|
||||||
|
* @param {string} pointName - The name of the point.
|
||||||
|
* @param {string} pointColor - The color of the point in CSS color string format.
|
||||||
|
* @param {number} timestamp - The timestamp in UNIX milliseconds indicating when the point was added.
|
||||||
|
* @returns {Entity} The Cesium Entity representing the added point.
|
||||||
|
*/
|
||||||
|
function addPoint(latitude, longitude, altitude, pointName, pointColor, pointSize, type, timestamp) {
|
||||||
|
// Convert latitude, longitude, altitude to Cartesian coordinates (ECEF)
|
||||||
|
const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, altitude);
|
||||||
|
|
||||||
|
// Create a point entity
|
||||||
|
const pointEntity = viewer.entities.add({
|
||||||
|
position,
|
||||||
|
point: {
|
||||||
|
color: Cesium.Color.fromCssColorString(pointColor),
|
||||||
|
pixelSize: pointSize,
|
||||||
|
},
|
||||||
|
label: (type === "radar") ? {
|
||||||
|
text: pointName,
|
||||||
|
showBackground: true,
|
||||||
|
backgroundColor: Cesium.Color.BLACK,
|
||||||
|
font: '14px sans-serif',
|
||||||
|
pixelOffset: new Cesium.Cartesian2(0, -20),
|
||||||
|
} : undefined,
|
||||||
|
properties: {
|
||||||
|
timestamp,
|
||||||
|
type,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return pointEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', function () {
|
||||||
|
|
||||||
|
// add radar points
|
||||||
|
const radar_names = new URLSearchParams(
|
||||||
|
window.location.search).get('url').split('&');
|
||||||
|
var radar_config_url = radar_names.map(
|
||||||
|
url => `http://${url}/api/config`);
|
||||||
|
if (this.window.location.protocol === "https:") {
|
||||||
|
radar_config_url = radar_config_url.map(
|
||||||
|
url => url.replace(/^http:/, 'https:'));
|
||||||
|
}
|
||||||
|
var style_radar = {};
|
||||||
|
style_radar.color = 'rgba(0, 0, 0, 1.0)';
|
||||||
|
style_radar.pointSize = 10;
|
||||||
|
style_radar.type = "radar";
|
||||||
|
style_radar.timestamp = Date.now();
|
||||||
|
radar_config_url.forEach(url => {
|
||||||
|
console.log(url);
|
||||||
|
fetch(url)
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Network response was not ok');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
// add radar rx and tx
|
||||||
|
addPoint(
|
||||||
|
data.location.rx.latitude,
|
||||||
|
data.location.rx.longitude,
|
||||||
|
data.location.rx.altitude,
|
||||||
|
data.location.rx.name,
|
||||||
|
style_radar.color,
|
||||||
|
style_radar.pointSize,
|
||||||
|
style_radar.type,
|
||||||
|
style_radar.timestamp
|
||||||
|
);
|
||||||
|
addPoint(
|
||||||
|
data.location.tx.latitude,
|
||||||
|
data.location.tx.longitude,
|
||||||
|
data.location.tx.altitude,
|
||||||
|
data.location.tx.name,
|
||||||
|
style_radar.color,
|
||||||
|
style_radar.pointSize,
|
||||||
|
style_radar.type,
|
||||||
|
style_radar.timestamp
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// Handle errors during fetch
|
||||||
|
console.error('Error during fetch:', error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// get detection data URL
|
||||||
|
|
||||||
|
// get truth URL
|
||||||
|
|
||||||
|
// call event loop
|
||||||
|
event_loop();
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
function event_loop() {
|
||||||
|
|
||||||
|
//console.log(Date.now());
|
||||||
|
|
||||||
|
setTimeout(event_loop, 1000);
|
||||||
|
|
||||||
|
}
|
|
@ -4,17 +4,19 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
import math
|
||||||
|
|
||||||
class AdsbAssociator:
|
class AdsbAssociator:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@class AdsbAssociator
|
@class AdsbAssociator
|
||||||
@brief A class for associating detections of the same target.
|
@brief A class for associating detections of the same target.
|
||||||
@details Girst associate ADS-B truth with each radar detection.
|
@details First associate ADS-B truth with each radar detection.
|
||||||
Then associate over multiple radars.
|
Then associate over multiple radars.
|
||||||
@see blah2 at https://github.com/30hours/blah2.
|
@see blah2 at https://github.com/30hours/blah2.
|
||||||
Uses truth data in delay-Doppler space from an adsb2dd server.
|
Uses truth data in delay-Doppler space from an adsb2dd server.
|
||||||
@see adsb2dd at https://github.com/30hours/adsb2dd.
|
@see adsb2dd at https://github.com/30hours/adsb2dd.
|
||||||
|
@todo Add adjustable window for associating truth/detections.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -33,6 +35,7 @@ class AdsbAssociator:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assoc_detections = {}
|
assoc_detections = {}
|
||||||
|
assoc_detections_radar = []
|
||||||
|
|
||||||
for radar in radar_list:
|
for radar in radar_list:
|
||||||
|
|
||||||
|
@ -50,26 +53,56 @@ class AdsbAssociator:
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
print(f"Error fetching data from {url}: {e}")
|
print(f"Error fetching data from {url}: {e}")
|
||||||
adsb_detections = None
|
adsb_detections = None
|
||||||
|
continue
|
||||||
|
|
||||||
# associate radar and truth
|
# associate radar and truth
|
||||||
print(adsb_detections, flush=True)
|
assoc_detections_radar.append(self.process_1_radar(
|
||||||
|
radar, radar_data[radar]["detection"], adsb_detections))
|
||||||
|
|
||||||
|
# associate detections between radars
|
||||||
|
|
||||||
|
print(assoc_detections_radar, flush=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#print(radar_list, flush=True)
|
def process_1_radar(self, radar, radar_detections, adsb_detections):
|
||||||
#print(radar_data, flush=True)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def process_1_radar(self, radar_detections, adsb_detections):
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@brief Associate detections between 1 radar/truth pair.
|
@brief Associate detections between 1 radar/truth pair.
|
||||||
@param radar_detections (str): JSON of blah2 radar detections.
|
@details Output 1 detection per truth point.
|
||||||
@param adsb_detections (str): JSON of adsb2dd truth detections.
|
@param radar (str): Name of radar to process.
|
||||||
@return str: JSON of associated detections.
|
@param radar_detections (dict): blah2 radar detections.
|
||||||
|
@param adsb_detections (dict): adsb2dd truth detections.
|
||||||
|
@return dict: Associated detections.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
assoc_detections = {}
|
||||||
|
distance_window = 10
|
||||||
|
|
||||||
|
for aircraft in adsb_detections:
|
||||||
|
|
||||||
|
if 'delay' in radar_detections:
|
||||||
|
|
||||||
|
if 'delay' in adsb_detections[aircraft] and len(radar_detections['delay']) >= 1:
|
||||||
|
|
||||||
|
# distance from aircraft to all detections
|
||||||
|
closest_point, distance = self.closest_point(
|
||||||
|
adsb_detections[aircraft]['delay'],
|
||||||
|
adsb_detections[aircraft]['doppler'],
|
||||||
|
radar_detections['delay'],
|
||||||
|
radar_detections['doppler']
|
||||||
|
)
|
||||||
|
|
||||||
|
if distance < distance_window:
|
||||||
|
|
||||||
|
assoc_detections[aircraft] = {
|
||||||
|
'radar': radar,
|
||||||
|
'delay': closest_point[0],
|
||||||
|
'doppler': closest_point[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return assoc_detections
|
||||||
|
|
||||||
def generate_api_url(self, radar, radar_data):
|
def generate_api_url(self, radar, radar_data):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -99,8 +132,23 @@ class AdsbAssociator:
|
||||||
"&tx=" + str(tx_lat) + "," +
|
"&tx=" + str(tx_lat) + "," +
|
||||||
str(tx_lon) + "," +
|
str(tx_lon) + "," +
|
||||||
str(tx_alt) +
|
str(tx_alt) +
|
||||||
"&fc=" + str(fc) +
|
"&fc=" + str(fc/1000000) +
|
||||||
"&server=" + "http://" + str(adsb)
|
"&server=" + "http://" + str(adsb)
|
||||||
)
|
)
|
||||||
|
|
||||||
return api_query
|
return api_query
|
||||||
|
|
||||||
|
def closest_point(self, x1, y1, x_coords, y_coords):
|
||||||
|
|
||||||
|
x1, y1 = float(x1), float(y1)
|
||||||
|
x_coords = [float(x) for x in x_coords]
|
||||||
|
y_coords = [float(y) for y in y_coords]
|
||||||
|
|
||||||
|
distances = [math.sqrt((x - x1)**2 + (y - y1)**2) for x, y in zip(x_coords, y_coords)]
|
||||||
|
min_distance_index = distances.index(min(distances))
|
||||||
|
|
||||||
|
closest_x = x_coords[min_distance_index]
|
||||||
|
closest_y = y_coords[min_distance_index]
|
||||||
|
distance = distances[min_distance_index]
|
||||||
|
|
||||||
|
return [closest_x, closest_y], distance
|
|
@ -76,8 +76,6 @@ async def event():
|
||||||
"config": radar_config[i]
|
"config": radar_config[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
print(radar_dict, flush=True)
|
|
||||||
|
|
||||||
# main processing
|
# main processing
|
||||||
for item in api_event:
|
for item in api_event:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue