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
servers = [
{"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 = [
{"name": "ADSB Associator", "id": "adsb-associator"}

View file

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

View file

@ -281,16 +281,17 @@ function removeEntitiesOlderThanAndFade(entityType, maxAgeSeconds, baseAlpha) {
const type = entity.properties["type"].getValue();
const timestamp = entity.properties["timestamp"].getValue();
if (entity.properties && entity.properties["type"] &&
entity.properties["type"].getValue() === entityType &&
Date.now()-timestamp > maxAgeSeconds*1000) {
entity.properties["type"].getValue() === entityType) {
if (Date.now()-timestamp > maxAgeSeconds*1000) {
viewer.entities.remove(entity);
}
else {
entity.point.color = new Cesium.Color.fromAlpha(
entity.point.color.getValue(), baseAlpha*(1-(Date.now()-timestamp)/(maxAgeSeconds*1000)));
}
else {
entity.point.color = new Cesium.Color.fromAlpha(
entity.point.color.getValue(), baseAlpha*(1-(Date.now()-timestamp)/(maxAgeSeconds*1000)));
}
}
}
}
function removeEntitiesByType(entityType) {

View file

@ -58,7 +58,7 @@ class Message:
with conn:
while True:
data = conn.recv(8096)
data = conn.recv(30000)
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(8096).decode()
reply = client_socket.recv(30000).decode()
return reply
except ConnectionRefusedError:
print(f"Connection to {self.host}:{self.port} refused.")

View file

@ -44,6 +44,8 @@ class EllipsoidParametric:
for target in assoc_detections:
print(target, flush=True)
target_samples = {}
target_samples[target] = {}
for radar in assoc_detections[target]:
@ -73,20 +75,48 @@ class EllipsoidParametric:
radar["radar"]
)
print(ellipsoid.yaw, flush=True)
print(ellipsoid.pitch, flush=True)
samples = self.sample(ellipsoid, radar["delay"], 20)
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
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 Use ECEF because distance measure is simple over LLA.
@param ellipsoid (Ellipsoid): The ellipsoid object to use.
@param bistatic_range (float): Bistatic range for ellipsoid.
@param n (int): Number of points to generate.
@ -101,51 +131,39 @@ class EllipsoidParametric:
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)]
# ])
R = np.array([
[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)],
[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
a = (bistatic_range+ellipsoid.distance)/2
b = np.sqrt(a**2 - (ellipsoid.distance/2)**2)
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')
# x = a * np.cos(u)
# y = b * np.sin(u) * np.cos(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)
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, np.dot(R, R2)) + ellipsoid.midpoint
#r_1 = np.dot(r, R) + ellipsoid.midpoint
r_1 = np.dot(r, R)
#r_1 = r
a, b, c = Geometry.ecef2lla(
ellipsoid.midpoint[0], ellipsoid.midpoint[1], ellipsoid.midpoint[2])
output = []
for i in range(len(r_1)):
x, y, z = Geometry.enu2ecef(r_1[i][0], r_1[i][1], r_1[i][2],
a, b, c)
r_1[i] = [x, y, z]
# points to ECEF
x, y, z = Geometry.enu2ecef(
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

@ -182,4 +182,11 @@ class Geometry:
u = cos_lat * t + sin_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
self.midpoint = [(f1[0]+f2[0])/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])
vector_enu = Geometry.ecef2enu(f1[0], f1[1], f1[2],
midpoint_lla[0], midpoint_lla[1], midpoint_lla[2])
self.yaw = -math.atan2(vector_enu[1], vector_enu[0])-math.pi/2
self.midpoint_lla[0], self.midpoint_lla[1], self.midpoint_lla[2])
self.yaw = -math.atan2(vector_enu[1], vector_enu[0])
self.pitch = math.atan2(vector_enu[2],
math.sqrt(vector_enu[0]**2 + vector_enu[1]**2))
self.distance = math.sqrt(

View file

@ -85,7 +85,7 @@ async def event():
key: radar_dict[key]
for key in item["server"]
if key in radar_dict
}
}
# associator selection
if item["associator"] == "adsb-associator":
@ -105,30 +105,36 @@ async def event():
associated_dets = associator.process(item["server"], 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
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'
)
pointsEcef = ellipsoidParametric.sample(ellipsoid, 6000, 15)
pointsLla = []
for point in pointsEcef:
lat, lon, alt = Geometry.ecef2lla(point[0], point[1], point[2])
pointsLla.append([round(lat, 4), round(lon, 4), round(alt)])
localised_dets["test"]["points"] = pointsLla
# 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'
# )
# points = ellipsoidParametric.sample(ellipsoid, 2000, 25)
# pointsLla = []
# for point in points:
# lat, lon, alt = Geometry.ecef2lla(point[0], point[1], point[2])
# pointsLla.append([round(lat, 3), round(lon, 3), round(alt)])
# localised_dets["test"]["points"] = pointsLla
# output data to API
item["detections_associated"] = associated_dets
@ -199,4 +205,4 @@ message_api_request.set_callback_message_received(callback_message_received)
if __name__ == "__main__":
threading.Thread(target=message_api_request.start_listener).start()
asyncio.run(main())
asyncio.run(main())