Start plotting target local

This commit is contained in:
30hours 2024-03-03 06:47:38 +00:00
parent 2c7c4358b7
commit 561baf5a35
8 changed files with 116 additions and 80 deletions

View file

@ -17,7 +17,8 @@ app = Flask(__name__)
# store state data # store state data
servers = [ servers = [
{"name": "radar4", "url": "radar4.30hours.dev"}, {"name": "radar4", "url": "radar4.30hours.dev"},
{"name": "radar5", "url": "radar5.30hours.dev"} {"name": "radar5", "url": "radar5.30hours.dev"},
{"name": "radar6", "url": "radar6.30hours.dev"}
] ]
associators = [ associators = [
{"name": "ADSB Associator", "id": "adsb-associator"} {"name": "ADSB Associator", "id": "adsb-associator"}

View file

@ -16,14 +16,17 @@ function event_radar() {
const target = data["detections_localised"][key]; const target = data["detections_localised"][key];
const points = target["points"]; const points = target["points"];
removeEntitiesByType("test"); console.log(target);
console.log(points);
removeEntitiesOlderThanAndFade("detection", 60, 0.5);
for (const point in points) { for (const point in points) {
addPoint( addPoint(
points[point][0], points[point][0],
points[point][1], points[point][1],
points[point][2], points[point][2],
"test", "detection",
style_point.color, style_point.color,
style_point.pointSize, style_point.pointSize,
style_point.type, style_point.type,
@ -46,7 +49,7 @@ function event_radar() {
} }
var style_point = {}; var style_point = {};
style_point.color = 'rgba(128, 0, 0, 1.0)'; style_point.color = 'rgba(0, 255, 0, 1.0)';
style_point.pointSize = 10; style_point.pointSize = 16;
style_point.type = "test"; style_point.type = "detection";
style_point.timestamp = Date.now(); style_point.timestamp = Date.now();

View file

@ -281,8 +281,9 @@ function removeEntitiesOlderThanAndFade(entityType, maxAgeSeconds, baseAlpha) {
const type = entity.properties["type"].getValue(); const type = entity.properties["type"].getValue();
const timestamp = entity.properties["timestamp"].getValue(); const timestamp = entity.properties["timestamp"].getValue();
if (entity.properties && entity.properties["type"] && if (entity.properties && entity.properties["type"] &&
entity.properties["type"].getValue() === entityType && entity.properties["type"].getValue() === entityType) {
Date.now()-timestamp > maxAgeSeconds*1000) {
if (Date.now()-timestamp > maxAgeSeconds*1000) {
viewer.entities.remove(entity); viewer.entities.remove(entity);
} }
else { else {
@ -290,7 +291,7 @@ function removeEntitiesOlderThanAndFade(entityType, maxAgeSeconds, baseAlpha) {
entity.point.color.getValue(), baseAlpha*(1-(Date.now()-timestamp)/(maxAgeSeconds*1000))); entity.point.color.getValue(), baseAlpha*(1-(Date.now()-timestamp)/(maxAgeSeconds*1000)));
} }
} }
}
} }
function removeEntitiesByType(entityType) { function removeEntitiesByType(entityType) {

View file

@ -58,7 +58,7 @@ class Message:
with conn: with conn:
while True: while True:
data = conn.recv(8096) data = conn.recv(30000)
if not data: if not data:
break break
decoded_data = data.decode() decoded_data = data.decode()
@ -82,7 +82,7 @@ class Message:
try: try:
client_socket.connect((self.host, self.port)) client_socket.connect((self.host, self.port))
client_socket.sendall(message.encode()) client_socket.sendall(message.encode())
reply = client_socket.recv(8096).decode() reply = client_socket.recv(30000).decode()
return reply return reply
except ConnectionRefusedError: except ConnectionRefusedError:
print(f"Connection to {self.host}:{self.port} refused.") print(f"Connection to {self.host}:{self.port} refused.")

View file

@ -44,6 +44,8 @@ class EllipsoidParametric:
for target in assoc_detections: for target in assoc_detections:
print(target, flush=True) print(target, flush=True)
target_samples = {}
target_samples[target] = {}
for radar in assoc_detections[target]: for radar in assoc_detections[target]:
@ -73,20 +75,48 @@ class EllipsoidParametric:
radar["radar"] radar["radar"]
) )
print(ellipsoid.yaw, flush=True) samples = self.sample(ellipsoid, radar["delay"], 20)
print(ellipsoid.pitch, flush=True) target_samples[target][radar["radar"]] = samples
self.sample(ellipsoid, radar["delay"], 10000) # find close points
radar_keys = list(target_samples[target].keys())
samples_intersect = {key: [] for key in radar_keys}
threshold = 200
for i in range(0, len(target_samples[target])-1):
print("", flush=True) for j in range(i+1, len(target_samples[target])):
for point1 in target_samples[target][radar_keys[i]]:
for point2 in target_samples[target][radar_keys[j]]:
if Geometry.distance_ecef(point1, point2) < threshold:
samples_intersect[radar_keys[i]].append(point1)
samples_intersect[radar_keys[j]].append(point2)
# remove duplicates and convert to LLA
output[target] = {}
output[target]["points"] = []
for key in radar_keys:
samples_intersect[key] = [list(t) for t in {tuple(point) for point in samples_intersect[key]}]
for i in range(len(samples_intersect[key])):
samples_intersect[key][i] = Geometry.ecef2lla(
samples_intersect[key][i][0],
samples_intersect[key][i][1],
samples_intersect[key][i][2])
output[target]["points"].append([
round(samples_intersect[key][i][0], 3),
round(samples_intersect[key][i][1], 3),
round(samples_intersect[key][i][2])])
return output return output
def sample(self, ellipsoid, bistatic_range, n): def sample(self, ellipsoid, bistatic_range, n):
""" """
@brief Generate a set of points for the ellipsoid. @brief Generate a set of ECEF points for the ellipsoid.
@details No arc length parametrisation. @details No arc length parametrisation.
@details Use ECEF because distance measure is simple over LLA.
@param ellipsoid (Ellipsoid): The ellipsoid object to use. @param ellipsoid (Ellipsoid): The ellipsoid object to use.
@param bistatic_range (float): Bistatic range for ellipsoid. @param bistatic_range (float): Bistatic range for ellipsoid.
@param n (int): Number of points to generate. @param n (int): Number of points to generate.
@ -101,51 +131,39 @@ class EllipsoidParametric:
phi = ellipsoid.pitch phi = ellipsoid.pitch
theta = ellipsoid.yaw 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)]
# ])
R = np.array([ R = np.array([
[np.cos(theta), -np.sin(theta)*np.cos(phi), np.sin(theta)*np.sin(phi)], [np.cos(theta), -np.sin(theta)*np.cos(phi), np.sin(theta)*np.sin(phi)],
[np.sin(theta), np.cos(theta)*np.cos(phi), -np.cos(theta)*np.sin(phi)], [np.sin(theta), np.cos(theta)*np.cos(phi), -np.cos(theta)*np.sin(phi)],
[0, np.sin(phi), np.cos(phi)] [0, np.sin(phi), np.cos(phi)]
]) ])
# rotation matrix normal
# theta = ellipsoid.pitch_plane
# phi = ellipsoid.yaw_plane
# R2 = 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 # compute samples vectorised
a = (bistatic_range+ellipsoid.distance)/2 a = (bistatic_range+ellipsoid.distance)/2
b = np.sqrt(a**2 - (ellipsoid.distance/2)**2) b = np.sqrt(a**2 - (ellipsoid.distance/2)**2)
u_values = np.linspace(0, 2 * np.pi, n) u_values = np.linspace(0, 2 * np.pi, n)
v_values = np.linspace(-np.pi, np.pi, n) v_values = np.linspace(-np.pi/2, np.pi/2, int(n/2))
u, v = np.meshgrid(u_values, v_values, indexing='ij') u, v = np.meshgrid(u_values, v_values, indexing='ij')
# x = a * np.cos(u) x = a * np.cos(u)
# y = b * np.sin(u) * np.cos(v) y = b * np.sin(u) * np.cos(v)
# z = b * np.sin(u) * np.sin(v) z = b * np.sin(u) * np.sin(v)
x = a * np.cos(u) * np.cos(v)
y = b * np.sin(u)
z = a * np.cos(u) * np.sin(v)
r = np.stack([x, y, z], axis=-1).reshape(-1, 3) r = np.stack([x, y, z], axis=-1).reshape(-1, 3)
#r_1 = np.dot(r, np.dot(R, R2)) + ellipsoid.midpoint
#r_1 = np.dot(r, R) + ellipsoid.midpoint
r_1 = np.dot(r, R) r_1 = np.dot(r, R)
#r_1 = r output = []
a, b, c = Geometry.ecef2lla(
ellipsoid.midpoint[0], ellipsoid.midpoint[1], ellipsoid.midpoint[2])
for i in range(len(r_1)): for i in range(len(r_1)):
x, y, z = Geometry.enu2ecef(r_1[i][0], r_1[i][1], r_1[i][2], # points to ECEF
a, b, c) x, y, z = Geometry.enu2ecef(
r_1[i] = [x, y, z] r_1[i][0], r_1[i][1], r_1[i][2],
ellipsoid.midpoint_lla[0],
ellipsoid.midpoint_lla[1],
ellipsoid.midpoint_lla[2])
# points to LLA
[x, y, z] = Geometry.ecef2lla(x, y, z)
# only store points above ground
if z > 0:
# convert back to ECEF for simple distance measurements
[x, y, z] = Geometry.lla2ecef(x, y, z)
output.append([round(x, 3), round(y, 3), round(z)])
return r_1.tolist() return output

View file

@ -183,3 +183,10 @@ class Geometry:
n = -sin_lat * t + cos_lat * w n = -sin_lat * t + cos_lat * w
return e, n, u return e, n, u
def distance_ecef(point1, point2):
return math.sqrt(
(point2[0]-point1[0])**2 +
(point2[1]-point1[1])**2 +
(point2[2]-point1[2])**2)

View file

@ -30,11 +30,11 @@ class Ellipsoid:
# dependent members # dependent members
self.midpoint = [(f1[0]+f2[0])/2, self.midpoint = [(f1[0]+f2[0])/2,
(f1[1]+f2[1])/2, (f1[2]+f2[2])/2] (f1[1]+f2[1])/2, (f1[2]+f2[2])/2]
midpoint_lla = Geometry.ecef2lla( self.midpoint_lla = Geometry.ecef2lla(
self.midpoint[0], self.midpoint[1], self.midpoint[2]) self.midpoint[0], self.midpoint[1], self.midpoint[2])
vector_enu = Geometry.ecef2enu(f1[0], f1[1], f1[2], vector_enu = Geometry.ecef2enu(f1[0], f1[1], f1[2],
midpoint_lla[0], midpoint_lla[1], midpoint_lla[2]) self.midpoint_lla[0], self.midpoint_lla[1], self.midpoint_lla[2])
self.yaw = -math.atan2(vector_enu[1], vector_enu[0])-math.pi/2 self.yaw = -math.atan2(vector_enu[1], vector_enu[0])
self.pitch = math.atan2(vector_enu[2], self.pitch = math.atan2(vector_enu[2],
math.sqrt(vector_enu[0]**2 + vector_enu[1]**2)) math.sqrt(vector_enu[0]**2 + vector_enu[1]**2))
self.distance = math.sqrt( self.distance = math.sqrt(

View file

@ -105,30 +105,36 @@ async def event():
associated_dets = associator.process(item["server"], radar_dict_item) associated_dets = associator.process(item["server"], radar_dict_item)
localised_dets = coordreg.process(associated_dets, radar_dict_item) localised_dets = coordreg.process(associated_dets, radar_dict_item)
if associated_dets:
print(associated_dets, flush=True)
#if localised_dets:
print(localised_dets, flush=True)
# tmp test # tmp test
localised_dets = {} # localised_dets = {}
localised_dets["test"] = {} # localised_dets["test"] = {}
x_tx, y_tx, z_tx = Geometry.lla2ecef( # 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']['latitude'],
radar_dict_item['radar4.30hours.dev']["config"]['location']['tx']['longitude'], # radar_dict_item['radar4.30hours.dev']["config"]['location']['tx']['longitude'],
radar_dict_item['radar4.30hours.dev']["config"]['location']['tx']['altitude'] # radar_dict_item['radar4.30hours.dev']["config"]['location']['tx']['altitude']
) # )
x_rx, y_rx, z_rx = Geometry.lla2ecef( # 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']['latitude'],
radar_dict_item['radar4.30hours.dev']["config"]['location']['rx']['longitude'], # radar_dict_item['radar4.30hours.dev']["config"]['location']['rx']['longitude'],
radar_dict_item['radar4.30hours.dev']["config"]['location']['rx']['altitude'] # radar_dict_item['radar4.30hours.dev']["config"]['location']['rx']['altitude']
) # )
ellipsoid = Ellipsoid( # ellipsoid = Ellipsoid(
[x_tx, y_tx, z_tx], # [x_tx, y_tx, z_tx],
[x_rx, y_rx, z_rx], # [x_rx, y_rx, z_rx],
'radar4.30hours.dev' # 'radar4.30hours.dev'
) # )
pointsEcef = ellipsoidParametric.sample(ellipsoid, 6000, 15) # points = ellipsoidParametric.sample(ellipsoid, 2000, 25)
pointsLla = [] # pointsLla = []
for point in pointsEcef: # for point in points:
lat, lon, alt = Geometry.ecef2lla(point[0], point[1], point[2]) # lat, lon, alt = Geometry.ecef2lla(point[0], point[1], point[2])
pointsLla.append([round(lat, 4), round(lon, 4), round(alt)]) # pointsLla.append([round(lat, 3), round(lon, 3), round(alt)])
localised_dets["test"]["points"] = pointsLla # localised_dets["test"]["points"] = pointsLla
# output data to API # output data to API
item["detections_associated"] = associated_dets item["detections_associated"] = associated_dets