mirror of
https://github.com/30hours/3lips.git
synced 2024-11-18 12:33:58 +00:00
A bunch of UI and formatting changes
This commit is contained in:
parent
ddd73a0d23
commit
88c99ed45e
9 changed files with 37 additions and 30 deletions
13
README.md
13
README.md
|
@ -1,12 +1,12 @@
|
||||||
# 3lips
|
# 3lips
|
||||||
|
|
||||||
Coordinate registration for multi-static radar using ellipse intersections. Not a dating app.
|
Target localisation for multi-static radar using ellipse intersections. Not a dating app.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Provides a JSON API for geolocation of targets given [blah2](http://github.com/30hours/blah2) radar nodes.
|
- Provides a JSON API for geolocation of targets given [blah2](http://github.com/30hours/blah2) radar nodes.
|
||||||
- Uses a [CesiumJS](http://github.com/CesiumGS/cesium) web front-end to visualise data.
|
- Uses a [CesiumJS](http://github.com/CesiumGS/cesium) web front-end to visualise data.
|
||||||
- Ability to compare a number of algorithms for coordinate registration.
|
- Ability to compare a number of algorithms for target localisation.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
@ -27,9 +27,13 @@ The association uses the following algorithm:
|
||||||
|
|
||||||
- ADS-B associator will associate the highest SNR target within some delay and Doppler boundary around the truth.
|
- ADS-B associator will associate the highest SNR target within some delay and Doppler boundary around the truth.
|
||||||
|
|
||||||
The coordinate registration uses 1 of the following algorithms:
|
The target localisation uses 1 of the following algorithms:
|
||||||
|
|
||||||
-
|
- **Ellipse parametric** samples an ellipse (2D) at 0 altitude. Find intersections between 3 or more ellipses such that the distance to each point is under some threshold.
|
||||||
|
|
||||||
|
- **Ellipsoid parametric** samples an ellipsoid (3D). Find intersections between 3 or more ellipsoids such that the distance to each point is under some threshold.
|
||||||
|
|
||||||
|
- **Spherical intersection** a closed form solution which applies when a common receiver or transmitter are used. As described in [Two Methods for Target Localization in Multistatic Passive Radar](https://ieeexplore.ieee.org/document/6129656).
|
||||||
|
|
||||||
The system architecture is as follows:
|
The system architecture is as follows:
|
||||||
|
|
||||||
|
@ -40,7 +44,6 @@ The system architecture is as follows:
|
||||||
## Future Work
|
## Future Work
|
||||||
|
|
||||||
- Implement an association algorithm that is not reliant on ADS-B truth.
|
- Implement an association algorithm that is not reliant on ADS-B truth.
|
||||||
- Add a variety of methods for solving the ellipse/ellipsoid intersection.
|
|
||||||
- Choose to use detection or track data from each radar.
|
- Choose to use detection or track data from each radar.
|
||||||
- Long term plots to show metrics such as 2D location accuracy to ADS-B, number of aircraft tracked, etc.
|
- Long term plots to show metrics such as 2D location accuracy to ADS-B, number of aircraft tracked, etc.
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ associators = [
|
||||||
# {"name": "Ellipsoid Parametric", "id": "ellipsoid-parametric"},
|
# {"name": "Ellipsoid Parametric", "id": "ellipsoid-parametric"},
|
||||||
# {"name": "Ellipsoid Parametric (Arc Length)", "id": "ellipsoid-parametric-arc"}
|
# {"name": "Ellipsoid Parametric (Arc Length)", "id": "ellipsoid-parametric-arc"}
|
||||||
# ]
|
# ]
|
||||||
coordregs = [
|
localisations = [
|
||||||
{"name": "Ellipsoid Parametric", "id": "ellipsoid-parametric"}
|
{"name": "Ellipsoid Parametric", "id": "ellipsoid-parametric"}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ message_api_request = Message('event', 6969)
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
return render_template("index.html", servers=servers, \
|
return render_template("index.html", servers=servers, \
|
||||||
associators=associators, coordregs=coordregs, adsbs=adsbs)
|
associators=associators, localisations=localisations, adsbs=adsbs)
|
||||||
|
|
||||||
# serve static files from the /app/public folder
|
# serve static files from the /app/public folder
|
||||||
@app.route('/public/<path:file>')
|
@app.route('/public/<path:file>')
|
||||||
|
|
|
@ -130,9 +130,17 @@ var viewer = new Cesium.Viewer("cesiumContainer", {
|
||||||
terrainProviderViewModels: terrainProviders,
|
terrainProviderViewModels: terrainProviders,
|
||||||
geocoder: false,
|
geocoder: false,
|
||||||
shouldAnimate: true,
|
shouldAnimate: true,
|
||||||
|
animation: false,
|
||||||
|
timeline: false,
|
||||||
selectionIndicator: false
|
selectionIndicator: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// keep data attribution, remove CesiumIon logo
|
||||||
|
var cesiumCredit = document.querySelector('.cesium-credit-logoContainer');
|
||||||
|
if (cesiumCredit) {
|
||||||
|
cesiumCredit.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds a point to Cesium viewer with specified parameters.
|
* @brief Adds a point to Cesium viewer with specified parameters.
|
||||||
* @param {number} latitude - The latitude of the point in degrees.
|
* @param {number} latitude - The latitude of the point in degrees.
|
||||||
|
|
|
@ -41,12 +41,12 @@ document.getElementById('buttonMap').addEventListener('click', function() {
|
||||||
// Get the form values
|
// Get the form values
|
||||||
var servers = document.querySelectorAll('.toggle-button.active');
|
var servers = document.querySelectorAll('.toggle-button.active');
|
||||||
var associator = document.querySelector('[name="associator"]').value;
|
var associator = document.querySelector('[name="associator"]').value;
|
||||||
var coordreg = document.querySelector('[name="coordreg"]').value;
|
var localisation = document.querySelector('[name="localisation"]').value;
|
||||||
var adsb = document.querySelector('[name="adsb"]').value;
|
var adsb = document.querySelector('[name="adsb"]').value;
|
||||||
|
|
||||||
// Construct the URL with the form values
|
// Construct the URL with the form values
|
||||||
var apiUrl = '?server=' + Array.from(servers).map(server => server.value).join('&server=');
|
var apiUrl = '?server=' + Array.from(servers).map(server => server.value).join('&server=');
|
||||||
var mapUrl = '/map/index.html' + apiUrl + '&associator=' + associator + '&coordreg=' + coordreg + '&adsb=' + adsb;
|
var mapUrl = '/map/index.html' + apiUrl + '&associator=' + associator + '&localisation=' + localisation + '&adsb=' + adsb;
|
||||||
|
|
||||||
// Redirect to the constructed URL
|
// Redirect to the constructed URL
|
||||||
window.location.href = mapUrl;
|
window.location.href = mapUrl;
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="jumbotron">
|
<div class="jumbotron">
|
||||||
<h1 class="display-4 text-center">3lips</h1>
|
<h1 class="display-4 text-center">3lips</h1>
|
||||||
<p class="lead">Coordinate registration for multi-static radar using ellipse intersections. Requires input of <a href="https://github.com/30hours/blah2" target="_blank">blah2</a> servers, and choice of algorithm for association and coordinate registration. This program exposes an API endpoint to generate geographic coordinates and a <a href="https://github.com/CesiumGS/cesium" target="_blank">Cesium</a> map for display.</p>
|
<p class="lead">Target localisation for multi-static radar using ellipse intersections. Requires input of <a href="https://github.com/30hours/blah2" target="_blank">blah2</a> servers, and choice of algorithm for association and target localisation. This program exposes an API endpoint to generate geographic coordinates and a <a href="https://github.com/CesiumGS/cesium" target="_blank">Cesium</a> map for display.</p>
|
||||||
<p class="lead">See <a href="https://github.com/30hours/3lips" target="_blank">github.com/30hours/3lips</a> for more details.</p>
|
<p class="lead">See <a href="https://github.com/30hours/3lips" target="_blank">github.com/30hours/3lips</a> for more details.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="calculator-form">
|
<div class="calculator-form">
|
||||||
|
@ -72,10 +72,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label fw-bold">Coordinate Registration:</label>
|
<label class="form-label fw-bold">Target Localisation:</label>
|
||||||
<select class="form-select" name="coordreg">
|
<select class="form-select" name="localisation">
|
||||||
{% for coordreg in coordregs %}
|
{% for localisation in localisations %}
|
||||||
<option value="{{ coordreg.id }}">{{ coordreg.name }}</option>
|
<option value="{{ localisation.id }}">{{ localisation.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
0
event/algorithm/localisation/EllipseParametric.py
Normal file
0
event/algorithm/localisation/EllipseParametric.py
Normal file
|
@ -24,15 +24,17 @@ class EllipsoidParametric:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.ellipsoids = []
|
self.ellipsoids = []
|
||||||
|
self.nSamples = 150
|
||||||
|
self.threshold = 800
|
||||||
|
|
||||||
def process(self, assoc_detections, radar_data):
|
def process(self, assoc_detections, radar_data):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@brief Perform coord registration using the ellipsoid parametric method.
|
@brief Perform target localisation using the ellipsoid parametric method.
|
||||||
@details Generate a (non arc-length) parametric ellipsoid for each node.
|
@details Generate a (non arc-length) parametric ellipsoid for each node.
|
||||||
@param assoc_detections (dict): JSON of blah2 radar detections.
|
@param assoc_detections (dict): JSON of blah2 radar detections.
|
||||||
@param radar_data (dict): JSON of adsb2dd truth detections.
|
@param radar_data (dict): JSON of adsb2dd truth detections.
|
||||||
@return str: JSON of associated detections.
|
@return dict: Dict of associated detections.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
output = {}
|
output = {}
|
||||||
|
@ -75,13 +77,12 @@ class EllipsoidParametric:
|
||||||
radar["radar"]
|
radar["radar"]
|
||||||
)
|
)
|
||||||
|
|
||||||
samples = self.sample(ellipsoid, radar["delay"]*1000, 120)
|
samples = self.sample(ellipsoid, radar["delay"]*1000, self.nSamples)
|
||||||
target_samples[target][radar["radar"]] = samples
|
target_samples[target][radar["radar"]] = samples
|
||||||
|
|
||||||
# find close points - ellipsoid 1 = master
|
# find close points - ellipsoid 1 = master
|
||||||
radar_keys = list(target_samples[target].keys())
|
radar_keys = list(target_samples[target].keys())
|
||||||
samples_intersect = []
|
samples_intersect = []
|
||||||
threshold = 500
|
|
||||||
|
|
||||||
# loop points in master ellipsoid
|
# loop points in master ellipsoid
|
||||||
for point1 in target_samples[target][radar_keys[0]]:
|
for point1 in target_samples[target][radar_keys[0]]:
|
||||||
|
@ -89,7 +90,7 @@ class EllipsoidParametric:
|
||||||
# loop over each other list
|
# loop over each other list
|
||||||
for i in range(1, len(radar_keys)):
|
for i in range(1, len(radar_keys)):
|
||||||
# loop points in other list
|
# loop points in other list
|
||||||
if not any(Geometry.distance_ecef(point1, point2) < threshold
|
if not any(Geometry.distance_ecef(point1, point2) < self.threshold
|
||||||
for point2 in target_samples[target][radar_keys[i]]):
|
for point2 in target_samples[target][radar_keys[i]]):
|
||||||
valid_point = False
|
valid_point = False
|
||||||
break
|
break
|
||||||
|
@ -124,11 +125,6 @@ class EllipsoidParametric:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# rotation matrix
|
# rotation matrix
|
||||||
phi = np.pi/2 - ellipsoid.pitch
|
|
||||||
theta = ellipsoid.yaw + np.pi/2
|
|
||||||
phi = np.deg2rad(3.834)
|
|
||||||
theta = -np.deg2rad(-77+90)
|
|
||||||
|
|
||||||
phi = ellipsoid.pitch
|
phi = ellipsoid.pitch
|
||||||
theta = ellipsoid.yaw
|
theta = ellipsoid.yaw
|
||||||
R = np.array([
|
R = np.array([
|
0
event/algorithm/localisation/SphericalIntersection.py
Normal file
0
event/algorithm/localisation/SphericalIntersection.py
Normal file
|
@ -14,7 +14,7 @@ import json
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from algorithm.associator.AdsbAssociator import AdsbAssociator
|
from algorithm.associator.AdsbAssociator import AdsbAssociator
|
||||||
from algorithm.coordreg.EllipsoidParametric import EllipsoidParametric
|
from algorithm.localisation.EllipsoidParametric import EllipsoidParametric
|
||||||
from common.Message import Message
|
from common.Message import Message
|
||||||
|
|
||||||
from data.Ellipsoid import Ellipsoid
|
from data.Ellipsoid import Ellipsoid
|
||||||
|
@ -94,11 +94,11 @@ async def event():
|
||||||
print("Error: Associator invalid.")
|
print("Error: Associator invalid.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# coord reg selection
|
# localisation selection
|
||||||
if item["coordreg"] == "ellipsoid-parametric":
|
if item["localisation"] == "ellipsoid-parametric":
|
||||||
coordreg = ellipsoidParametric
|
localisation = ellipsoidParametric
|
||||||
else:
|
else:
|
||||||
print("Error: Coord reg invalid.")
|
print("Error: Localisation invalid.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# processing
|
# processing
|
||||||
|
@ -108,7 +108,7 @@ async def event():
|
||||||
for key, value in associated_dets.items()
|
for key, value in associated_dets.items()
|
||||||
if isinstance(value, list) and len(value) >= 3
|
if isinstance(value, list) and len(value) >= 3
|
||||||
}
|
}
|
||||||
localised_dets = coordreg.process(associated_dets_3_radars, radar_dict_item)
|
localised_dets = localisation.process(associated_dets_3_radars, radar_dict_item)
|
||||||
|
|
||||||
if associated_dets:
|
if associated_dets:
|
||||||
print(associated_dets, flush=True)
|
print(associated_dets, flush=True)
|
||||||
|
|
Loading…
Reference in a new issue