Files
eSlider 3deaa382e1 feat(simulator): virtual drone fleet data generator
One process per drone: seeded patrol kinematics, sensor streams at
realistic rates, detection events, hot current/ blocks sealed into
Hive-partitioned Parquet, and the compact UDP state broadcast with
peer RSSI derivation. Scales via docker compose --scale.
2026-07-08 13:12:34 +01:00

81 lines
2.4 KiB
Python

"""Sensor row generators. Pure functions: (pose, rng, ts) -> row dict.
Every row carries int64 epoch nanoseconds. Values are emitted at full float
precision - quantization happens only in the broadcast payload, never in
stored telemetry.
"""
from __future__ import annotations
import math
import random
from typing import Any
from .flight import Pose
Row = dict[str, Any]
def imu_row(pose: Pose, rng: random.Random, ts_ns: int) -> Row:
return {
"ts_ns": ts_ns,
"accel_x": rng.gauss(0.0, 0.35),
"accel_y": rng.gauss(0.0, 0.35),
"accel_z": rng.gauss(-9.81, 0.25),
"gyro_x": math.radians(rng.gauss(pose.roll, 0.8)),
"gyro_y": math.radians(rng.gauss(pose.pitch, 0.8)),
"gyro_z": math.radians(rng.gauss(0.0, 0.5)),
}
def baro_row(pose: Pose, rng: random.Random, ts_ns: int) -> Row:
pressure = 101325.0 * math.exp(-pose.z / 8434.0) + rng.gauss(0.0, 4.0)
return {"ts_ns": ts_ns, "pressure_pa": pressure, "alt_est_m": pose.z + rng.gauss(0.0, 0.3)}
def temp_row(_pose: Pose, rng: random.Random, ts_ns: int) -> Row:
return {
"ts_ns": ts_ns,
"cpu_c": 55.0 + rng.gauss(0.0, 3.0),
"gpu_c": 62.0 + rng.gauss(0.0, 4.0),
"ambient_c": 24.0 + rng.gauss(0.0, 0.5),
}
def battery_row(_pose: Pose, rng: random.Random, ts_ns: int, elapsed_s: float, duration_s: float) -> Row:
level = max(0.0, 100.0 - 80.0 * elapsed_s / max(duration_s, 1.0) + rng.gauss(0.0, 0.2))
return {"ts_ns": ts_ns, "level_pct": level, "voltage_v": 22.2 * (0.85 + 0.15 * level / 100.0)}
DETECTION_CLASSES = ("vehicle", "person", "animal", "structure", "unknown")
def detection_row(pose: Pose, rng: random.Random, ts_ns: int) -> Row:
return {
"ts_ns": ts_ns,
"cls": rng.choice(DETECTION_CLASSES),
"confidence": round(rng.uniform(0.42, 0.99), 3),
"obj_x": pose.x + rng.uniform(-40.0, 40.0),
"obj_y": pose.y + rng.uniform(-40.0, 40.0),
"obj_z": rng.uniform(0.0, 5.0),
"ego_x": pose.x,
"ego_y": pose.y,
"ego_z": pose.z,
}
def state_row(pose: Pose, ts_ns: int) -> Row:
return {
"ts_ns": ts_ns,
"pos_x": pose.x,
"pos_y": pose.y,
"pos_z": pose.z,
"roll": pose.roll,
"pitch": pose.pitch,
"yaw": pose.yaw,
"vel_x": pose.vx,
"vel_y": pose.vy,
"vel_z": pose.vz,
"frame_ref": 0,
}