Files

294 lines
9.2 KiB
GDScript
Raw Permalink Normal View History

extends BaseSensorNode
class_name VehicleSensorNode
"""
Vehicle sensor can provide the following data fields:
- GPS
- Contributing satellites
- Accelerometer
- Magnetometer
- Gyroscope
"""
var max_data_length: int = 10
var gps_timestamps = []
var coordinates = []
var gps_positions = []
var altitudes = []
var alt_coefficients = []
var altitude_m:
get:
return _get_current_altitude()
var speed_data = []
var speed_coefficients = []
var speed_kmh:
get:
return _get_current_speed()
static var DOWN = Vector2(0, -1.)
var accel_timestamps = []
var g_vecs = []
var linear_vecs = []
var pitch_data = []
var pitch_rad: float
var roll_data = []
var roll_rad: float
var lateral_g_data = []
var x_coefficients = []
var y_coefficients = []
var lateral_accel:
get:
return _get_current_gs()
var mag_timestamps = []
var mag_vecs = []
var heading_data = []
var heading_rad: float
func _ready() -> void:
2026-07-08 20:58:21 -06:00
super._ready()
2026-08-01 18:19:21 -06:00
DataSignals.raw_data_received.connect(_on_raw_data_received)
#DataSignals.sat_data_received.connect(_on_sat_data_received)
DataSignals.accelerometer_data_received.connect(_on_accel_data_received)
#DataSignals.gyroscope_data_received.connect(_on_gyro_data_received)
func _get_sensor_class():
return "VEHICLE"
2026-08-01 18:19:21 -06:00
func _on_raw_data_received(source_ip: String, sensor_type: String, timestamp_list: Array, data: Array):
if source_ip != ip_address:
return
2026-08-01 18:19:21 -06:00
if sensor_type == "GPS":
var parsed_coordinates = [
(float(data[0]) / 10.**9) - 90,
(float(data[1]) / 10.**9) - 180,
(float(data[2]) / 1000.),
(float(data[3]) / 100.),
]
var speed = float(data[4]) / 1000000.
var dop = [
float(data[5]) / 1000.,
float(data[6]) / 1000.,
float(data[7]) / 1000.,
]
_on_gps_data_received(timestamp_list, parsed_coordinates, speed, dop)
if sensor_type == "ACCEL":
var accel = Vector3(
float(data[0]) / 1000000.,
float(data[1]) / 1000000.,
float(data[2]) / 1000000.
)
var linear_accel = Vector3(
float(data[3]) / 1000000.,
float(data[4]) / 1000000.,
float(data[5]) / 1000000.
)
var g_accel = Vector3(
float(data[6]) / 1000000.,
float(data[7]) / 1000000.,
float(data[8]) / 1000000.
)
_on_accel_data_received(timestamp_list, accel, linear_accel, g_accel)
func _on_gps_data_received(timestamp_list: Array, new_coordinates: Array, speed: float, dop: Array):
# coordinates = [lat rad, lon rad, alt m, geoid diff m]
# dop = [pdop, hdop, vdop]
var timestamp: float = 3600.*timestamp_list[0] + 60.*timestamp_list[1] + timestamp_list[2] + timestamp_list[3]
2026-07-08 20:58:21 -06:00
if gps_timestamps.size() > 0 and (timestamp - gps_timestamps[-1]) < -1:
gps_timestamps.clear()
coordinates.clear()
gps_positions.clear()
altitudes.clear()
speed_data.clear()
if gps_timestamps.size() == max_data_length and not TimeHelpers.is_timestamp_newer_24h(gps_timestamps[-1], timestamp):
return
var insert_idx = Bisect.reverse_bisect(gps_timestamps, timestamp)
2026-08-01 18:19:21 -06:00
var altitude = new_coordinates[2] + new_coordinates[3]
var radius_km = (new_coordinates[2] + new_coordinates[3] + Constants.EARTH_RADIUS_M) / 1000.
var pos_x = radius_km * sin(new_coordinates[1]) * cos(new_coordinates[0])
var pos_z = radius_km * sin(new_coordinates[1]) * sin(new_coordinates[0])
var pos_y = radius_km * cos(new_coordinates[1])
gps_timestamps.insert(insert_idx, timestamp)
coordinates.insert(insert_idx, [new_coordinates[0], new_coordinates[1]])
gps_positions.insert(insert_idx, Vector3(pos_x, pos_y, pos_z))
2026-08-01 18:19:21 -06:00
altitudes.insert(insert_idx, altitude)
speed_data.insert(insert_idx, speed)
if gps_timestamps.size() > max_data_length:
gps_timestamps.pop_back()
coordinates.pop_back()
gps_positions.pop_back()
altitudes.pop_back()
speed_data.pop_back()
_update_alt_coefficients()
_update_speed_coefficients()
func _on_sat_data_received(source_ip: String, timestamp: float):
if source_ip != ip_address:
return
2026-08-01 18:19:21 -06:00
func _on_accel_data_received(timestamp_list: Array, accel: Vector3, linear_accel: Vector3, g_accel: Vector3):
var timestamp: float = 3600.*timestamp_list[0] + 60.*timestamp_list[1] + timestamp_list[2] + timestamp_list[3]
2026-07-08 20:58:21 -06:00
if accel_timestamps.size() > 0 and (timestamp - accel_timestamps[-1]) < -1:
accel_timestamps.clear()
linear_vecs.clear()
g_vecs.clear()
pitch_data.clear()
roll_data.clear()
lateral_g_data.clear()
if accel_timestamps.size() == max_data_length and not TimeHelpers.is_timestamp_newer_24h(accel_timestamps[-1], timestamp):
return
var insert_idx = Bisect.reverse_bisect(accel_timestamps, timestamp)
var x_z = Vector2(g_accel.x, g_accel.z).normalized()
var y_z = Vector2(g_accel.y, g_accel.z).normalized()
var pitch = DOWN.angle_to(x_z)
var roll = y_z.angle_to(DOWN)
accel_timestamps.insert(insert_idx, timestamp)
linear_vecs.insert(insert_idx, linear_accel)
g_vecs.insert(insert_idx, g_accel)
pitch_data.insert(insert_idx, pitch)
roll_data.insert(insert_idx, roll)
var lateral_g = Vector2(linear_accel.x, linear_accel.y)
lateral_g_data.insert(insert_idx, lateral_g.normalized()*lateral_g.length())
if accel_timestamps.size() > max_data_length:
accel_timestamps.pop_back()
linear_vecs.pop_back()
g_vecs.pop_back()
pitch_data.pop_back()
roll_data.pop_back()
lateral_g_data.pop_back()
_update_avg_pitch()
_update_avg_roll()
_update_g_coefficients()
func _on_mag_data_received(source_ip: String, timestamp_list: Array, mag_vec: Vector3):
if source_ip != ip_address:
return
var timestamp: float = 3600.*timestamp_list[0] + 60.*timestamp_list[1] + timestamp_list[2] + timestamp_list[3]
2026-07-08 20:58:21 -06:00
if mag_timestamps.size() > 0 and (timestamp - mag_timestamps[-1]) < -1:
mag_timestamps.clear()
mag_vecs.clear()
heading_data.clear()
if mag_timestamps.size() == max_data_length and not TimeHelpers.is_timestamp_newer_24h(mag_timestamps[-1], timestamp):
return
var insert_idx = Bisect.reverse_bisect(mag_timestamps, timestamp)
var mag_2d = Vector2(mag_vec.x, mag_vec.y)
mag_2d.normalized()
var new_heading_rad = atan2(-mag_2d.y, mag_2d.x)
if new_heading_rad < 0:
new_heading_rad += 2*PI
mag_timestamps.insert(insert_idx, timestamp)
mag_vecs.insert(insert_idx, mag_vec)
heading_data.insert(insert_idx, new_heading_rad)
if mag_timestamps.size() > max_data_length:
mag_timestamps.pop_back()
mag_vecs.pop_back()
heading_data.pop_back()
func _on_gyro_data_received(source_ip: String, timestamp: float):
if source_ip != ip_address:
return
func get_derrivative(dataset: Array) -> Array:
if dataset.size() < 2:
return [0, []]
var deltas = []
var delta_sum = 0
for i in range(dataset.size()-1):
deltas.append(dataset[i+1] - dataset[i])
2026-08-01 18:19:21 -06:00
return [float(delta_sum) / deltas.size(), deltas]
func get_array_avg(dataset: Array):
var data_sum = 0
for i in dataset:
data_sum += i
return data_sum / dataset.size()
func get_coefficients(dataset: Array, order: int):
if order == 0:
return []
if dataset.size() <= order:
order = dataset.size() - 1
var coefficients = []
var tmp_dataset = dataset
var dx_result: Array
for i in range(order):
dx_result = get_derrivative(tmp_dataset)
coefficients.append(dx_result[0])
tmp_dataset = dx_result[1]
return coefficients
func _update_alt_coefficients():
if gps_timestamps.size() < 2:
return
alt_coefficients = get_coefficients(altitudes, 2)
func _get_current_altitude():
if gps_timestamps.size() < 3:
return null
var current_timestamp = TimeHelpers.get_current_sensor_time()
var time_diff = max(0, TimeHelpers.calc_time_diff_24h(gps_timestamps[0], current_timestamp))
var current_value = altitudes[0]
for idx in range(alt_coefficients.size()):
current_value += alt_coefficients[idx] * (time_diff ** idx+1)
return current_value
func _update_speed_coefficients():
if gps_timestamps.size() < 2:
return
speed_coefficients = get_coefficients(speed_data, 2)
func _get_current_speed():
if gps_timestamps.size() < 3:
return
var current_timestamp = TimeHelpers.get_current_sensor_time()
var time_diff = max(0, TimeHelpers.calc_time_diff_24h(gps_timestamps[-1], current_timestamp))
var current_value = speed_data[0]
for idx in range(speed_coefficients.size()):
current_value += speed_coefficients[idx] * (time_diff ** idx+1)
return current_value
func _update_g_coefficients():
if accel_timestamps.size() < 2:
return
var x_dataset = []
var y_dataset = []
for i in lateral_g_data:
x_dataset.append(i.x)
y_dataset.append(i.y)
x_coefficients = get_coefficients(x_dataset, 3)
y_coefficients = get_coefficients(y_dataset, 3)
func _get_current_gs():
if accel_timestamps.size() < 3:
return
var current_timestamp = TimeHelpers.get_current_sensor_time()
var time_diff = max(0, TimeHelpers.calc_time_diff_24h(accel_timestamps[0], current_timestamp))
var current_x = lateral_g_data[0].x
var current_y = lateral_g_data[0].y
for idx in range(speed_coefficients.size()):
current_x += x_coefficients[idx] * (time_diff ** idx+1)
current_y += y_coefficients[idx] * (time_diff ** idx+1)
return Vector2(current_x, current_y)
func _update_avg_pitch():
var pitch_sum = 0
for i in range(accel_timestamps.size()):
pitch_sum += pitch_data[i]
pitch_rad = pitch_sum / pitch_data.size()
func _update_avg_roll():
var roll_sum = 0
for i in range(accel_timestamps.size()):
roll_sum += roll_data[i]
roll_rad = roll_sum / roll_data.size()
func _update_avg_heading():
var heading_sum = 0
for i in range(min(mag_timestamps.size(), 2)):
heading_sum += heading_data[i]
heading_rad = heading_sum / heading_data.size()