2026-07-04 18:22:23 -06:00
|
|
|
# server_node.gd
|
|
|
|
|
class_name ServerNode
|
|
|
|
|
extends Node
|
|
|
|
|
|
|
|
|
|
signal camera_position_updated(pos_x, pos_y, pos_z)
|
|
|
|
|
signal camera_rotation_updated(rot_x, rot_y, rot_z)
|
|
|
|
|
signal sensor_point_generated(pos_x, pos_y, pos_z)
|
|
|
|
|
|
|
|
|
|
var server = UDPServer.new()
|
|
|
|
|
var port = 5001
|
|
|
|
|
var awaiting_sensors = {}
|
|
|
|
|
var invalid_sensors = {}
|
|
|
|
|
var valid_sensors = {}
|
|
|
|
|
|
2026-07-06 13:57:09 -06:00
|
|
|
var use_thread: bool = false
|
2026-07-04 23:49:20 -06:00
|
|
|
var thread: Thread
|
|
|
|
|
var mutex: Mutex
|
2026-07-06 13:57:09 -06:00
|
|
|
var exit_thread = true
|
2026-07-04 23:49:20 -06:00
|
|
|
|
|
|
|
|
var signal_queue = []
|
|
|
|
|
|
2026-07-04 18:22:23 -06:00
|
|
|
func _ready():
|
|
|
|
|
ServerSignals.sensor_approved.connect(_on_sensor_approved)
|
|
|
|
|
ServerSignals.sensor_declined.connect(_on_sensor_declined)
|
|
|
|
|
server.listen(port, "0.0.0.0")
|
|
|
|
|
if not server.is_listening():
|
|
|
|
|
print('Unable to listen on port: ', port)
|
|
|
|
|
print('Listening on port: ', port)
|
2026-07-04 23:49:20 -06:00
|
|
|
|
|
|
|
|
mutex = Mutex.new()
|
2026-07-06 13:57:09 -06:00
|
|
|
if use_thread:
|
|
|
|
|
thread = Thread.new()
|
|
|
|
|
print('Starting UDP Server thread')
|
|
|
|
|
thread.start(_thread_function)
|
|
|
|
|
else:
|
|
|
|
|
print('UDP server running in single threaded mode')
|
2026-07-04 23:49:20 -06:00
|
|
|
|
|
|
|
|
func _process(delta: float) -> void:
|
2026-07-06 13:57:09 -06:00
|
|
|
if not use_thread:
|
|
|
|
|
_process_connections()
|
2026-07-04 23:49:20 -06:00
|
|
|
while signal_queue.size() > 0:
|
|
|
|
|
mutex.lock()
|
|
|
|
|
var signal_data = signal_queue.pop_front()
|
|
|
|
|
mutex.unlock()
|
|
|
|
|
if signal_data[0] == "new_sensor_connected":
|
|
|
|
|
SensorSignals.new_sensor_connected.emit(signal_data[1], signal_data[2])
|
|
|
|
|
elif signal_data[0] == "sensor_request_received":
|
|
|
|
|
ServerSignals.sensor_request_received.emit(signal_data[1], signal_data[2])
|
|
|
|
|
elif signal_data[0] == "on_time_data_received":
|
|
|
|
|
TimeHelpers.on_time_data_received(signal_data[1])
|
|
|
|
|
elif signal_data[0] == "gps_data_received":
|
|
|
|
|
DataSignals.gps_data_received.emit(signal_data[1], signal_data[2], signal_data[3], signal_data[4], signal_data[5])
|
|
|
|
|
elif signal_data[0] == "sat_data_received":
|
|
|
|
|
DataSignals.sat_data_received.emit(signal_data[1], signal_data[2], signal_data[3], signal_data[4])
|
|
|
|
|
elif signal_data[0] == "accelerometer_data_received":
|
|
|
|
|
DataSignals.accelerometer_data_received.emit(signal_data[1], signal_data[2], signal_data[3], signal_data[4], signal_data[5])
|
|
|
|
|
elif signal_data[0] == "magnetometer_data_received":
|
|
|
|
|
DataSignals.magnetometer_data_received.emit(signal_data[1], signal_data[2], signal_data[3])
|
2026-07-08 20:58:21 -06:00
|
|
|
elif signal_data[0] == "lidar_2d_data_received":
|
|
|
|
|
DataSignals.lidar_2d_data_received.emit(signal_data[1], signal_data[2], signal_data[3], signal_data[4])
|
2026-07-04 23:49:20 -06:00
|
|
|
|
|
|
|
|
func _exit_tree() -> void:
|
2026-07-06 13:57:09 -06:00
|
|
|
if use_thread:
|
|
|
|
|
mutex.lock()
|
|
|
|
|
exit_thread = true
|
|
|
|
|
mutex.unlock()
|
|
|
|
|
thread.wait_to_finish()
|
2026-07-04 18:22:23 -06:00
|
|
|
|
|
|
|
|
func _on_sensor_approved(sensor_ip: String):
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
2026-07-04 18:22:23 -06:00
|
|
|
valid_sensors[sensor_ip] = awaiting_sensors[sensor_ip]
|
|
|
|
|
if sensor_ip in awaiting_sensors:
|
|
|
|
|
awaiting_sensors.erase(sensor_ip)
|
2026-07-04 23:49:20 -06:00
|
|
|
signal_queue.append(["new_sensor_connected", sensor_ip, valid_sensors[sensor_ip]])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
|
|
|
|
|
func _on_sensor_declined(sensor_ip: String):
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
2026-07-04 18:22:23 -06:00
|
|
|
invalid_sensors[sensor_ip] = 0
|
|
|
|
|
if sensor_ip in awaiting_sensors:
|
|
|
|
|
awaiting_sensors.erase(sensor_ip)
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
|
2026-07-04 23:49:20 -06:00
|
|
|
func _thread_function():
|
2026-07-06 13:57:09 -06:00
|
|
|
print('UDP Server thread started')
|
2026-07-04 23:49:20 -06:00
|
|
|
while true:
|
|
|
|
|
mutex.lock()
|
|
|
|
|
var should_exit = exit_thread
|
|
|
|
|
mutex.unlock()
|
|
|
|
|
if should_exit:
|
|
|
|
|
break
|
|
|
|
|
_process_connections()
|
2026-07-04 18:22:23 -06:00
|
|
|
|
2026-07-04 23:49:20 -06:00
|
|
|
func _process_connections():
|
2026-07-04 18:22:23 -06:00
|
|
|
server.poll()
|
|
|
|
|
if server.is_connection_available():
|
|
|
|
|
var peer = server.take_connection()
|
|
|
|
|
var packet = peer.get_packet()
|
|
|
|
|
if not _verify_checksum(packet):
|
|
|
|
|
print('Received packet with incorrect checksum: %s' % peer.get_packet_ip())
|
|
|
|
|
else:
|
2026-07-04 23:49:20 -06:00
|
|
|
|
|
|
|
|
_handle_new_connection(peer, packet)
|
2026-07-04 18:22:23 -06:00
|
|
|
|
2026-07-04 23:49:20 -06:00
|
|
|
func _handle_new_connection(peer: PacketPeerUDP, packet: PackedByteArray):
|
2026-07-04 18:22:23 -06:00
|
|
|
if packet.get(0) == 0xD4 and packet.get(1) == 0x53:
|
|
|
|
|
"""
|
|
|
|
|
| 2 bytes | 2 bytes | 2 bytes | variable length | 2 bytes |
|
|
|
|
|
| packet start | message class | payload length | payload | checksum |
|
|
|
|
|
First two bytes are the frame start - always 0xD4 and 0x53
|
|
|
|
|
The two bytes for message class and id identify the packet contents
|
|
|
|
|
The two bytes for payload length should be read as an u16 integer
|
|
|
|
|
and indicate the payload size.
|
|
|
|
|
The 2-byte checksuim is calculated over the packet's contents - the message
|
|
|
|
|
class and id bytes, payload length byts, and the payload itself.
|
|
|
|
|
The formula is:
|
|
|
|
|
var ck_a = 0
|
|
|
|
|
var ck_b = 0
|
|
|
|
|
for i in range(2, packet.size()-2):
|
|
|
|
|
ck_a += packet.get(i)
|
|
|
|
|
ck_b += ck_a
|
|
|
|
|
packet[packet.size()-2] = ck_a
|
|
|
|
|
packet[packet.size()-1] = ck_b
|
|
|
|
|
"""
|
|
|
|
|
_handle_six_fps_message(peer, packet)
|
|
|
|
|
else:
|
|
|
|
|
print("Received: '%s' %s:%s" % [packet.get_string_from_utf8(), peer.get_packet_ip(), peer.get_packet_port()])
|
|
|
|
|
|
|
|
|
|
func _calculate_checksum(packet) -> Array:
|
|
|
|
|
var ck_a = 0
|
|
|
|
|
var ck_b = 0
|
|
|
|
|
for i in range(2, packet.size()-2):
|
|
|
|
|
ck_a += packet.get(i)
|
|
|
|
|
ck_b += ck_a
|
|
|
|
|
return [ck_a % 0x100, ck_b % 0x100]
|
|
|
|
|
|
|
|
|
|
func _verify_checksum(packet) -> bool:
|
|
|
|
|
var calculated_checksum = _calculate_checksum(packet)
|
|
|
|
|
return packet.get(packet.size()-1) == calculated_checksum[1] and packet.get(packet.size()-2) == calculated_checksum[0]
|
|
|
|
|
|
|
|
|
|
func _handle_six_fps_message(peer: PacketPeerUDP, packet: PackedByteArray):
|
|
|
|
|
var peer_ip = peer.get_packet_ip()
|
|
|
|
|
if peer_ip in invalid_sensors:
|
|
|
|
|
return
|
|
|
|
|
if peer_ip in awaiting_sensors:
|
|
|
|
|
return
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
2026-07-04 18:22:23 -06:00
|
|
|
var valid_sensor: bool = peer.get_packet_ip() in valid_sensors
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
var message_class = packet.get(2)
|
|
|
|
|
var message_id = packet.get(3)
|
|
|
|
|
if (not valid_sensor) and (message_class == 0x6e and message_id == 0x77):
|
|
|
|
|
_handle_new_peer_request(peer_ip, packet)
|
|
|
|
|
if not valid_sensor:
|
|
|
|
|
return
|
|
|
|
|
elif message_class == 0x6e and message_id == 0x4e:
|
|
|
|
|
_handle_heartbeat_packet(peer_ip, packet)
|
|
|
|
|
elif message_class == 0x2a and message_id == 0xac:
|
|
|
|
|
_handle_time_packet(peer_ip, packet)
|
|
|
|
|
elif message_class == 0x2a and message_id == 0x7c:
|
|
|
|
|
#print('GPS packet received')
|
|
|
|
|
_handle_position_packet(peer_ip, packet)
|
|
|
|
|
elif message_class == 0x2a and message_id == 0x7b:
|
|
|
|
|
#print('Sats packet received')
|
|
|
|
|
_handle_gps_sats_packet(peer_ip, packet)
|
|
|
|
|
elif message_class == 0x2a and message_id == 0xfa:
|
|
|
|
|
#print('Accel packet received')
|
|
|
|
|
_handle_accel_packet(peer_ip, packet)
|
|
|
|
|
elif message_class == 0x2a and message_id == 0x39:
|
|
|
|
|
#print('Mag packet received')
|
|
|
|
|
_handle_magnetic_packet(peer_ip, packet)
|
2026-07-08 20:58:21 -06:00
|
|
|
elif message_class == 0x2a and message_id == 0x6f:
|
|
|
|
|
_handle_lidar_2d_packet(peer_ip, packet)
|
2026-07-04 18:22:23 -06:00
|
|
|
elif message_class == 0x2a and message_id == 0xa7:
|
|
|
|
|
_handle_public_key_packet(peer_ip, packet)
|
|
|
|
|
elif message_class == 0x2a and message_id == 0x5e: # not in use
|
|
|
|
|
_handle_euler_packet(peer_ip, packet)
|
|
|
|
|
elif message_class == 0x2a and message_id == 0xba: # not in use
|
|
|
|
|
_handle_quaternion_packet(peer_ip, packet)
|
|
|
|
|
|
|
|
|
|
func _handle_new_peer_request(peer_ip: String, packet: PackedByteArray):
|
|
|
|
|
"""
|
|
|
|
|
offset | size | type | description
|
|
|
|
|
4 | 1 byte | bool | peer provides datetime
|
|
|
|
|
5 | 1 byte | bool | peer provides gps
|
|
|
|
|
6 | 1 byte | bool | peer provides accelerometer
|
|
|
|
|
7 | 1 byte | bool | peer provides gyroscope
|
|
|
|
|
8 | 1 byte | bool | peer provides magnetometer
|
|
|
|
|
9 | 1 byte | bool | peer provides euler orientation
|
|
|
|
|
10 | 1 byte | bool | peer provides quaternion orientation
|
|
|
|
|
"""
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
2026-07-06 13:57:09 -06:00
|
|
|
if packet.get(4) == 0xf1:
|
|
|
|
|
awaiting_sensors[peer_ip] = "VEHICLE"
|
|
|
|
|
elif packet.get(4) == 0x23:
|
|
|
|
|
awaiting_sensors[peer_ip] = "LIDAR_2D"
|
2026-07-04 23:49:20 -06:00
|
|
|
signal_queue.append(["sensor_request_received", peer_ip, awaiting_sensors[peer_ip]])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
|
|
|
|
|
func _parse_timestamp_slice(packet: PackedByteArray):
|
2026-07-04 23:49:20 -06:00
|
|
|
var hour = float(packet.decode_u8(0))
|
|
|
|
|
var minute = float(packet.decode_u8(1))
|
|
|
|
|
var second = float(packet.decode_u8(2))
|
|
|
|
|
var nanosecond = float(packet.decode_u32(3)) * pow(10,-9)
|
2026-07-04 18:22:23 -06:00
|
|
|
return [hour, minute, second, nanosecond]
|
|
|
|
|
|
|
|
|
|
func _handle_heartbeat_packet(peer_ip: String, packet: PackedByteArray):
|
|
|
|
|
#print('heartbeat')
|
2026-07-04 23:49:20 -06:00
|
|
|
var timestamp_list = _parse_timestamp_slice(packet.slice(4, 11))
|
|
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["on_time_data_received", timestamp_list])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
#print(hour, ' ', minute, ' ', second)
|
|
|
|
|
|
|
|
|
|
func _handle_time_packet(peer_ip: String, packet: PackedByteArray):
|
|
|
|
|
#print('time')
|
|
|
|
|
var timestamp_list = _parse_timestamp_slice(packet.slice(4, 11))
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["on_time_data_received", timestamp_list])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
#print(timestamp_list)
|
|
|
|
|
|
|
|
|
|
func _handle_position_packet(peer_ip: String, packet: PackedByteArray):
|
|
|
|
|
#print('gps')
|
|
|
|
|
var timestamp_list = _parse_timestamp_slice(packet.slice(4, 11))
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["on_time_data_received", timestamp_list])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
var lat: float = (float(packet.decode_u64(11)) / 10.**9) - 90
|
|
|
|
|
var lon: float = (float(packet.decode_u64(19)) / 10.**9) - 180
|
|
|
|
|
var alt_neg = packet.decode_u8(27)
|
|
|
|
|
var alt_m: float = packet.decode_u32(28) / 1000.0 * (-1. ** alt_neg)
|
|
|
|
|
var geoid_neg = packet.decode_u8(32)
|
|
|
|
|
var goid_m: float = packet.decode_u16(33) / 100 * (-1. ** geoid_neg)
|
|
|
|
|
var speed_neg = packet.decode_u8(35)
|
|
|
|
|
var speed_kmh: float = packet.decode_u32(36) / 1000000.0 * (-1 ** speed_neg)
|
|
|
|
|
var pdop: float = packet.decode_u32(40) / 1000.0
|
|
|
|
|
var hdop: float = packet.decode_u32(44) / 1000.0
|
|
|
|
|
var vdop: float = packet.decode_u32(49) / 1000.0
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["gps_data_received", peer_ip, timestamp_list, [lat, lon, alt_m, goid_m], speed_kmh, [pdop, hdop, vdop]])
|
2026-07-08 20:58:21 -06:00
|
|
|
signal_queue.append(["raw_data_received", peer_ip, "GPS", timestamp_list, {"lat": lat, "lon": lon, "alt_m": alt_m, "speed_kmh": speed_kmh, "pdop": pdop, "hdop": hdop, "vdop": vdop}])
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
|
|
|
|
|
func _handle_gps_sats_packet(peer_ip: String, packet: PackedByteArray):
|
|
|
|
|
var timestamp_list = _parse_timestamp_slice(packet.slice(4, 11))
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["on_time_data_received", timestamp_list])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
var ga = packet.decode_u8(11)
|
|
|
|
|
var gb = packet.decode_u8(12)
|
|
|
|
|
var gi = packet.decode_u8(13)
|
|
|
|
|
var gl = packet.decode_u8(14)
|
|
|
|
|
var gp = packet.decode_u8(15)
|
|
|
|
|
var gq = packet.decode_u8(16)
|
|
|
|
|
var gn = packet.decode_u8(17)
|
|
|
|
|
var num_entries = packet.decode_u8(18)
|
|
|
|
|
var sats_offset = 19
|
|
|
|
|
var el_offset = 4
|
|
|
|
|
var az_offset = 5
|
|
|
|
|
var sat_data = []
|
|
|
|
|
for i in range(num_entries):
|
|
|
|
|
var start_offset = sats_offset + (i * 7)
|
|
|
|
|
var sat_name = packet.slice(start_offset, start_offset + el_offset).get_string_from_ascii()
|
|
|
|
|
var elevation = packet.decode_u8(start_offset+el_offset)
|
|
|
|
|
var azimuth = packet.decode_u16(start_offset+az_offset)
|
|
|
|
|
sat_data.append([sat_name, elevation, azimuth])
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["sat_data_received", peer_ip, timestamp_list, [ga, gb, gi, gl, gp, gq, gn], sat_data])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
|
|
|
|
|
func _handle_accel_packet(peer_ip: String, packet: PackedByteArray):
|
|
|
|
|
var timestamp_list = _parse_timestamp_slice(packet.slice(4, 11))
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["on_time_data_received", timestamp_list])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
var neg = packet.decode_u8(11)
|
|
|
|
|
var x = (packet.decode_s32(12) / 1000000.0) * (-1 ** neg)
|
|
|
|
|
neg = packet.decode_u8(16)
|
|
|
|
|
var y = (packet.decode_s32(17) / 1000000.0) * (-1 ** neg)
|
|
|
|
|
neg = packet.decode_u8(21)
|
|
|
|
|
var z = (packet.decode_s32(22) / 1000000.0) * (-1 ** neg)
|
|
|
|
|
|
|
|
|
|
neg = packet.decode_u8(26)
|
|
|
|
|
var lin_x = (packet.decode_s32(27) / 1000000.0) * (-1 ** neg)
|
|
|
|
|
neg = packet.decode_u8(31)
|
|
|
|
|
var lin_y = (packet.decode_s32(32) / 1000000.0) * (-1 ** neg)
|
|
|
|
|
neg = packet.decode_u8(36)
|
|
|
|
|
var lin_z = (packet.decode_s32(37) / 1000000.0) * (-1 ** neg)
|
|
|
|
|
|
|
|
|
|
neg = packet.decode_u8(41)
|
|
|
|
|
var g_x = (packet.decode_s32(42) / 1000000.0) * (-1 ** neg)
|
|
|
|
|
neg = packet.decode_u8(46)
|
|
|
|
|
var g_y = (packet.decode_s32(47) / 1000000.0) * (-1 ** neg)
|
|
|
|
|
neg = packet.decode_u8(51)
|
|
|
|
|
var g_z = (packet.decode_s32(52) / 1000000.0) * (-1 ** neg)
|
|
|
|
|
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["accelerometer_data_received", peer_ip, timestamp_list, Vector3(x, y, z), Vector3(lin_x, lin_y, lin_z), Vector3(g_x, g_y, g_z)])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
|
|
|
|
|
func _handle_magnetic_packet(peer_ip: String, packet: PackedByteArray):
|
|
|
|
|
var timestamp_list = _parse_timestamp_slice(packet.slice(4, 11))
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["on_time_data_received", timestamp_list])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
var neg = packet.decode_u8(11)
|
|
|
|
|
var x = (packet.decode_u32(12) / 1000.0) * (-1 ** neg)
|
|
|
|
|
neg = packet.decode_u8(16)
|
|
|
|
|
var y = (packet.decode_u32(17) / 1000.0) * (-1 ** neg)
|
|
|
|
|
neg = packet.decode_u8(21)
|
|
|
|
|
var z = (packet.decode_u32(22) / 1000.0) * (-1 ** neg)
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["magnetometer_data_received", peer_ip, timestamp_list, Vector3(x, y, z)])
|
|
|
|
|
mutex.unlock()
|
2026-07-08 20:58:21 -06:00
|
|
|
|
|
|
|
|
func _handle_lidar_2d_packet(peer_ip: String, packet: PackedByteArray):
|
|
|
|
|
var timestamp_list = _parse_timestamp_slice(packet.slice(4, 11))
|
|
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["on_time_data_received", timestamp_list])
|
|
|
|
|
mutex.unlock()
|
|
|
|
|
var point_count = packet.decode_u8(11)
|
|
|
|
|
var point_data = []
|
|
|
|
|
for idx in range(point_count):
|
|
|
|
|
var offset = idx * 7
|
|
|
|
|
var angle: float = float(packet.decode_u32(12 + offset)) / 10000
|
|
|
|
|
var distance: float = float(packet.decode_u16(12 + offset + 4)) / 1000
|
|
|
|
|
var intensity: int = packet.decode_u8(12 + offset + 6)
|
|
|
|
|
point_data.append([angle, distance, intensity])
|
|
|
|
|
signal_queue.append(["lidar_2d_data_received", peer_ip, timestamp_list, point_count, point_data])
|
|
|
|
|
|
2026-07-04 18:22:23 -06:00
|
|
|
func _handle_public_key_packet(peer_ip: String, packet: PackedByteArray):
|
|
|
|
|
var timestamp_list = _parse_timestamp_slice(packet.slice(4, 11))
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["on_time_data_received", timestamp_list])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
func _handle_euler_packet(peer_ip: String, packet: PackedByteArray):
|
|
|
|
|
var timestamp_list = _parse_timestamp_slice(packet.slice(4, 11))
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["on_time_data_received", timestamp_list])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
func _handle_quaternion_packet(peer_ip: String, packet: PackedByteArray):
|
|
|
|
|
var timestamp_list = _parse_timestamp_slice(packet.slice(4, 11))
|
2026-07-04 23:49:20 -06:00
|
|
|
mutex.lock()
|
|
|
|
|
signal_queue.append(["on_time_data_received", timestamp_list])
|
|
|
|
|
mutex.unlock()
|
2026-07-04 18:22:23 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
func _handle_racebox_message(delta, packet):
|
|
|
|
|
#print(packet.size())
|
|
|
|
|
var year = packet.decode_u16(10)
|
|
|
|
|
var month = packet.decode_u8(12)
|
|
|
|
|
var day = packet.decode_u8(13)
|
|
|
|
|
var hour = packet.decode_u8(14)
|
|
|
|
|
var minute = packet.decode_u8(15)
|
|
|
|
|
var second = packet.decode_u8(16)
|
|
|
|
|
var dt_valid_flags = _to_binary(packet.decode_u8(17))
|
|
|
|
|
var valid_date = int(dt_valid_flags[-1]) == 1
|
|
|
|
|
var valid_time = int(dt_valid_flags[-2]) == 1
|
|
|
|
|
var dt_fully_resolved = int(dt_valid_flags[-3]) == 1
|
|
|
|
|
var valid_mag_dec = int(dt_valid_flags[-4]) == 1
|
|
|
|
|
var time_accuracy_ns = packet.decode_u32(18)
|
|
|
|
|
var nano_second = packet.decode_u32(22)
|
|
|
|
|
var fix_status_flags = _to_binary(packet.decode_u8(27))
|
|
|
|
|
var dt_flags = _to_binary(packet.decode_u8(28))
|
|
|
|
|
var num_sv = packet.decode_u8(29)
|
|
|
|
|
var lon_deg = float(packet.decode_u32(30)) / (10**7)
|
|
|
|
|
var lat_deg = float(packet.decode_u32(34)) / (10**7)
|
|
|
|
|
var wgs_alt_m = float(packet.decode_u32(38)) / (10**3) + 6378.137
|
|
|
|
|
var msl_alt_m = float(packet.decode_u32(42)) / (10**3) + 6378.137
|
|
|
|
|
var horz_accuracy_m = float(packet.decode_u32(46)) / (10**3)
|
|
|
|
|
var vert_accuracy_m = float(packet.decode_u32(50)) / (10**3)
|
|
|
|
|
var speed_mps = float(packet.decode_s32(54)) / (10**3)
|
|
|
|
|
var heading_deg = float(packet.decode_s32(58)) / (10**5)
|
|
|
|
|
var speed_accuracy_mps = float(packet.decode_u32(62)) / (10**3)
|
|
|
|
|
var heading_accuracy_deg = float(packet.decode_u32(66)) / (10**5)
|
|
|
|
|
var pdop = float(packet.decode_u16(70)) / 100
|
|
|
|
|
var lat_lon_flags = _to_binary(packet.decode_u8(72))
|
|
|
|
|
var battery_status = _to_binary(packet.decode_u8(73))
|
|
|
|
|
var g_force_x = packet.decode_s16(74) # milli-g
|
|
|
|
|
var g_force_y = packet.decode_s16(76) # milli-g
|
|
|
|
|
var g_force_z = packet.decode_s16(78) # milli-g
|
|
|
|
|
var rot_rate_x_dps = float(packet.decode_s16(80)) / 100
|
|
|
|
|
var rot_rate_y_dps = float(packet.decode_s16(82)) / 100
|
|
|
|
|
var rot_rate_z_dps = float(packet.decode_s16(84)) / 100
|
|
|
|
|
if num_sv > 0:
|
|
|
|
|
var lon_rad = deg_to_rad(lon_deg)
|
|
|
|
|
var lat_rad = deg_to_rad(lat_deg)
|
|
|
|
|
var sensor_pos_x = wgs_alt_m * sin(lon_rad) * cos(lat_rad)
|
|
|
|
|
var sensor_pos_y = wgs_alt_m * sin(lon_rad) * sin(lat_rad)
|
|
|
|
|
var sensor_pos_z = wgs_alt_m * cos(lon_rad)
|
|
|
|
|
var camera_pos_x = (wgs_alt_m+1) * sin(lon_rad) * cos(lat_rad)
|
|
|
|
|
var camera_pos_y = (wgs_alt_m+1) * sin(lon_rad) * sin(lat_rad)
|
|
|
|
|
var camera_pos_z = (wgs_alt_m+1) * cos(lon_rad)
|
|
|
|
|
camera_position_updated.emit(camera_pos_x, camera_pos_y, camera_pos_z)
|
|
|
|
|
camera_rotation_updated.emit(deg_to_rad(rot_rate_x_dps) * delta, deg_to_rad(rot_rate_y_dps) * delta, deg_to_rad(rot_rate_z_dps) * delta)
|
|
|
|
|
sensor_point_generated.emit(sensor_pos_x, sensor_pos_y, sensor_pos_z)
|
|
|
|
|
else:
|
|
|
|
|
print(Time.get_datetime_string_from_system())
|
|
|
|
|
print("GPS has no sources")
|
|
|
|
|
|
|
|
|
|
func _to_binary(intValue: int) -> String:
|
|
|
|
|
var bin_str: String = ""
|
|
|
|
|
while intValue > 0:
|
|
|
|
|
bin_str = str(intValue & 1) + bin_str
|
|
|
|
|
intValue = intValue >> 1
|
|
|
|
|
return bin_str
|
|
|
|
|
|