The operator scenario uses ten radars on a 12 km ring, a 9 km loiter, a blast that waits for the closest point, and up to three launches when a closer drone is on the line. Co-authored-by: Cursor <cursoragent@cursor.com>
22 KiB
Overwatch: Project Specification
Attack-vehicle presets: projectile_preset selects shahed_136, shahed_238, cruise_missile, ballistic_reentry, prop_drone, custom, or uniform random selection. The five named profiles are built from open-source vehicle data (Wikipedia infoboxes, CSIS Missile Threat, manufacturer spec sheets, defense-press reporting); mass, reference area, and drag coefficient are per-class engineering estimates sampled once per run and documented in simulation/presets.py. scenario.projectile_profile records realized values and scenario.projectile_preset_requested records the selection mode.
The attacker is a point mass that starts mid-flight on the approach ring at its sampled entry altitude, aimed at the randomized strike point on a terminal glide. With terminal_guidance_enabled (default on) it models a GPS/INS-aided loitering munition: a sliding-intercept descent law commands the velocity toward the strike point (descent rate = altitude / time-to-target, capped at 60 degrees) and holds cruise speed by commanding thrust that balances gravity + drag, capped at terminal_thrust_m_s2 and re-aimed at guidance_command_rate_hz. The thrust command is held constant across each RK4 step so noise is not redrawn within a step. With guidance disabled the vehicle is a pure unpowered ballistic point mass (gravity + wind-relative quadratic drag). No preset forces an exact cruise speed when guidance is off, and the guidance law steers to the strike point rather than following a prescribed trajectory.
Status: authoritative initial backend specification. This specification follows source inspection of all three requested repositories; it will be revised when validation or domain requirements expose a conflict.
1. Goals
Build a backend-authoritative, reproducible, configurable physical simulation of projectiles and multirotor/aircraft entities, with noisy observation and control, environmental effects, interception events, Monte Carlo results, and a transport-independent state stream. The system must preserve ground truth separately from observations and expose enough state for a later renderer to draw entities and trajectories without calculating physics.
2. Non-goals
No client-side simulation, combat doctrine, operational deployment, or claim of flight-qualified fidelity. A Vue 3 + Vite bootstrap and telemetry console have since been added under frontend/; a full 2D/3D visualization remains outside this baseline until renderer, map, and camera requirements are supplied. This is a research/engineering simulation framework with explicit model limits, not a certified 6-DOF aerodynamic model of any real vehicle.
3. Architecture and backend responsibilities
Python package defense_sim under src/. Simulation code owns configuration, random generators, state, physics, environment, sensing, guidance, event detection, raw runs, and statistics. Socket.IO is an adapter that publishes engine snapshots/events; it must not mutate or calculate simulation reality. Pure model modules must be usable without the server.
Proposed modules: simulation/{engine,state,scenarios}, physics/{vector,integrator,atmosphere,environment,turbulence}, entities/{projectile,drone}, sensors/{models,tracking}, guidance/{controllers,interception}, statistics/{metrics,monte_carlo}, server/{socketio_server,events}. Shared immutable configuration dataclasses and explicit SI units are preferred over per-entity ad hoc constants.
4. Coordinate frames and state
Use SI units and a world NED frame: x north, y east, z down; altitude is -z. Body-frame quantities are marked as such. Ground-truth rigid-body state includes position, velocity, acceleration, quaternion orientation [w,x,y,z], body angular rates, and actuator state. Observations and estimates are separate timestamped values with covariance/error metadata. Quaternion normalization occurs after integration. Events and serialized vectors include frame and units in schema/version metadata.
5. Projectile model
Point-mass translational equations: p_dot=v; v_dot=g + (F_thrust + F_aero)/m. Drag is opposite relative air velocity and initially quadratic, F_d=-0.5*rho*Cd*A*|v_air|*v_air; mass, area, drag coefficient, gravity, launch state, optional thrust curve, and uncertainty distributions are configuration. A launch command initializes one sampled initial condition; no later velocity or position edits are permitted. Ground/impact and interception are continuous within-step events, refined by interpolation/root finding. Projectile attitude is omitted unless a later body/aero model needs it.
Reference finding: georgeh1ll/Projectile-Motion-Simulator contains simulate_projectile_motion, which decomposes launch speed into x/y components and advances position at 0.01 s with constant gravity. It is useful as a basic vacuum trajectory sanity check and launch-angle UI concept. It has no drag, atmosphere, uncertainty, or collision model and no LICENSE file in the cloned revision; no code is copied. Correct public URL is https://github.com/georgeh1ll/Projectile-Motion-Simulator (the supplied ...Simulatoryou URL does not resolve).
6. Attack drone and defense drone models
Both drone classes use the same physical dynamics and differ only in configuration, mission/guidance policy, and sensors. Initial multirotor model: rigid body with mass, diagonal inertia (configurable), quaternion attitude, motor thrust/torque lag, rotor thrust and torque limits, gravity, translational aerodynamic drag, and moments; actuator commands pass through delay, lag, saturation, and noise before forces/moments. Position/velocity targets become bounded acceleration/attitude/thrust commands through a cascaded controller, never direct state assignments. Rate, acceleration, speed, tilt, climb/descent, and motor limits are explicit. Fixed-wing configuration may later use aerodynamic coefficients and control surfaces; it is a separate model, not a hidden approximation.
Reference finding: riverjiang187/PyFlightSim source has a 13-element rigid-body state (NED position, body velocity, quaternion, body rates), Newton-Euler force/moment dynamics including gravity and gyroscopic terms, quaternion kinematics, RK4, configurable aerodynamic coefficients, cascaded PID autopilot, ISA, Dryden gust shaping, and IMU/GPS/air-data/estimator modules. We adapt the separations, state representation, RK4 and quaternion approach, atmosphere, turbulence concepts, and bounded cascaded control. No code is copied in this initial implementation. Its model is fixed-wing oriented, has simplified diagonal inertia/aerodynamics, and must be independently checked before reuse.
Reference finding: nb-programmer/dronesim source separates physics engine, actor, action/control interface, and sensors; SimpleUAVDronePhysics maps RC commands through velocity/altitude/yaw PID-like controls to thrust and includes operation states. Its implementation mixes centimeter-like implicit units, per-tick motion, direct angle/velocity updates and simple multiplicative drag; sensor base and IMU are mostly stubs. We adapt the command/actuator/interface separation and lifecycle ideas, not its dynamics or numeric constants. No code is copied in this initial implementation.
7. Environment, atmosphere and turbulence
Environment configuration provides altitude-aware ISA temperature, pressure, density, speed of sound, and dynamic viscosity, with documented valid altitude range and configurable deviations. Wind is a deterministic configured vector/field plus optional seeded variation. Air-relative velocity drives aerodynamic loads. Dryden turbulence is a stateful stochastic filter driven by the run RNG and configured intensity/scale lengths; gust velocity changes air-relative force calculations. It is never applied as visual-only position noise. Wind/turbulence update cadence is distinct from physics integration cadence.
8. Sensors, tracking, uncertainty and randomness
Each run owns a seeded generator; entity-specific generators use stable seed derivation so call ordering in unrelated entities does not alter the result. Noise configuration supports bias, standard deviation, correlation/AR processes, quantization, latency, missed observations, and actuator variation. Actual-minus-estimated errors are reported as vectors and norms, with sensor, tracking, guidance, and actuator error kept distinct. Controllers consume estimates only. A deterministic mode disables stochastic terms but retains explicitly configured biases/delays.
9. Guidance and control
Guidance consumes timestamped track estimates. Commands pass through configurable command latency, controller, actuator dynamics/saturation, and then physical force/moment evaluation. The baseline controller is bounded position/velocity-to-acceleration control for multirotors; interceptor guidance is bounded pursuit/lead guidance using estimated target state and configured speed/turn/acceleration limits. No prediction is written into physical position. Record command, actuator output, and tracking/control error.
10. Interception
Interception is a swept relative-motion sphere test across each integration interval, with event time/position refined within the step. A hit occurs when separation is within the configured combined collision radius while both entities are active. Record IDs, time, interpolated positions/velocities, miss distance, estimated time-to-intercept, and relevant observation/guidance errors. Closest approach is measured for misses. There is no magical proximity event or teleportation.
City-circle defender activation
A configurable protected circle defaults to 10 km radius in NED. Independent radar and grounded staging rings default to 12 km and 28 km. Radar position measurements feed Stone Soup covariance-aware constant-velocity tracking; duplicate and stale samples are rejected. Trajectory assignment requires at least three distinct sample times spanning >=0.5 s and bounded velocity covariance (largest variance <=2500 (m/s)^2). This is an explicit educational evidence gate, not operational qualification.
Age-propagated estimates drive a declared constant-velocity forecast. Exactly three available defense drones are selected by 3D distance to its finite future segment through the first protected-circle entry, with entity-id tie breaking. A necessary kinematic screen reports infeasibility; it does not guarantee arrival. Assignment is separate from command delivery. Launch/replan commands incur computation, serialization and propagation delay, dropped initial commands retry up to three times, and failures or terminated threats release reservations. Collision participants cannot be reused.
Defenders progress in the estimated horizontal travel direction while following an altitude reference derived from actual accumulated horizontal distance. Quintic smoothstep is default, cubic and exponential are selectable. Smoothstep uses h0+(H-h0)*f(clip(x/L,0,1)); quintic has zero first and second endpoint derivatives. User-selected L requests a finite ascent distance. Automatic L uses a 20% nominal peak climb-rate margin, with a 500 m floor, and remains a heuristic. Reference updates are rate limited and do not directly change truth position/velocity. Radar updates revise delivered references; delayed bearing-only IR can refine requested altitude using an uncertain radar prior. Visibility and stale samples affect acquisition.
11. Simulation loop and integration
Fixed-step simulation clock. At each physics step: update scheduled environment stochastic states; deliver due sensor samples and update tracks; update guidance/control on their own configured rates; advance actuator states; integrate all coupled physical entities with RK4 or a justified method; normalize attitude; find ground/collision/interception events over the step; update run metrics; publish immutable snapshots at an independent output cadence. Step ordering and event queue use simulation time only. RK stages evaluate forces from stage state and the same held actuator/environment sample so stochastic noise is not redrawn within a single step.
12. Monte Carlo and statistics
Scenario configuration is data. run_many derives one reproducible child seed per run and retains configuration, seed, final/event summaries, and optional sampled trajectories. Aggregation reports run count; hit/interception probability; miss probability and distance mean/median/std/min/max; interception-time mean/median; detection/track timing; and error summaries. Results are grouped by projectile ID/type under interception_by_projectile and are transport-neutral. Raw runs remain serializable so aggregates can be recomputed.
13. Backend event/state schema
Every packet has schema_version, run_id, sequence, simulation_time, and kind. A state packet includes entity identity/type/status, position, velocity, acceleration, quaternion, angular velocity, actuator/control summary, and trajectory history or incremental trajectory samples; environment includes atmosphere/wind/turbulence; observations/tracks include estimate, timestamp, uncertainty and ground-truth error only in simulation/debug output; statistics are structured sections overall, scenario, timing, error, interception_by_projectile. Event packets include typed collision/interception/impact/detection/error events. JSON values use finite numbers only. Socket.IO event names are defined in server/events.py; clients subscribe to simulation_state, simulation_event, simulation_statistics, and simulation_error. Streaming can throttle/coalesce snapshots without affecting physics.
14. Configuration
Validated dataclasses (and JSON/YAML serialization at the boundary) define integration/control/sensor/stream rates, environment, body/motor/projectile parameters, uncertainty distributions, scenario entities, collision radii, and seed. Invalid units, negative mass, nonpositive timestep, and inconsistent limits fail before a run. Defaults are educational example values, never described as representative of deployed equipment.
15. Determinism and replay
Same software version, configuration, seed, step schedule, and platform floating-point behavior must reproduce results within documented numerical tolerance. RNG state/seed and configuration hash are kept in raw run metadata. No wall clock drives physics. Socket client timing cannot affect engine time.
16. Validation strategy
Tests cover analytical vacuum projectile motion; quadratic drag energy/speed behavior; ISA anchor values and monotonicity; RK4 convergence and constant acceleration; quaternion normalization; force/actuator bounds; drone turn/acceleration/altitude constraints; sensor error and seed reproducibility; Dryden finite output/statistical bounds; swept collision/interception edge cases; estimation error signs; Monte Carlo aggregate recomputation; event/state serialization. Golden analytic solutions and physically reasonable bounds are preferred to self-referential expected values. CI will run unit tests and a small performance smoke benchmark. These tests are planned deliverables; do not claim fidelity beyond tested envelopes.
17. Performance
Physics, controller, navigation sensor, radar scan, wireless link, and state-stream rates are distinct simulation-time schedules. The normal operator workflow does not expose integrator steps or random seeds: a run creates and records its own seed, and ends at physical interception/ground impact. Physics rate and model timing remain backend configuration. Snapshots are streamed at up to 20 Hz by wall-clock output gating; full-history event cursors prevent duplicate replay. Live runs advance physics against absolute monotonic deadlines at 1× elapsed wall time and yield cooperatively; offline engine and Monte Carlo runs remain unpaced. Slow live runs catch up without skipping fixed steps. Runs are isolated per authenticated connection and canceled on disconnect. Physics benchmarks remain necessary for larger entity counts and Monte Carlo; networking must not change fixed simulation time.
18. Transport architecture
python-socketio ASGI server adapts the engine's async snapshot/event stream. It supports starting/stopping runs, state subscription, and server-side errors; it accepts scenario and device configuration but does not accept client-authored entity state or compute physics. Engine APIs work without Socket.IO. CORS is configurable through SIM_ALLOWED_ORIGINS. The Vue client uses socket.io-client to submit scenario/device configuration and render received state/events.
19. Known limitations
Initial core is a configurable engineering approximation. ISA layering, simplified turbulence, rigid-body multirotor rotor model, aerodynamic coefficients, sensor covariance, guidance and ground interaction require independent calibration. No real vehicle validation data is currently supplied. Ground collision uses a flat datum. Interception models geometric contact, not blast/fragment effects. Python floating-point determinism is not guaranteed bit-for-bit across platforms.
Device timing and link assumptions
The AERIS-10 profile is based on repository firmware in firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp. With 16 chirps at PRI1=167 μs and PRI2=175 μs, a 175.4 μs guard, three phase patterns for each of 15 elevation positions, and four 1 ms stepper pulses, one azimuth frame is 258.133 ms. Fifty azimuth positions imply a 12.90665 s same-direction revisit. The model checks a 50-position azimuth sector and a 31-beam elevation fan; finite horizontal sector width (7.2° per mechanical step) and 3° elevation spacing are approximations pending measured antenna beam patterns. AERIS-10N/10X maximum range is configured as 3 km/20 km from the root README.
The repository's simulate_trajectory_precision.py uses 10 Hz observations, 2 m range sigma, 0.5° azimuth/elevation sigma, 1 m/s Doppler sigma, and 7.1 ms fixed latency. Those values are adopted as R&D sensor/error and processing-delay assumptions, not verified AERIS-10 performance. The firmware-derived scan cadence supersedes that script's uniform 10 Hz update assumption for radar detections.
The drone navigation sensor defaults to 10 Hz with 2 m position sigma, 0.4 m/s velocity sigma, and 10 ms onboard processing. Flight control defaults to 50 Hz; physics integrates at 100 Hz; actuator lag uses the existing 0.25 s time constant. Drone command and telemetry share a configurable, half-duplex, serialized wireless R&D link: 20 Hz send slots, 250 kbit/s, 64-byte telemetry / 48-byte command payloads, 24-byte framing overhead, 50 ms one-way delay, 5 ms Gaussian jitter, 10 ms command computation, and zero packet loss. These are explicit baselines for field tuning, not claims about a selected drone radio. The field proposal for that radio is docs/drone-command-link.md. The simulator has not been switched to it. Wired radar-to-control reporting uses the 7.1 ms fixed-delay assumption. Link queueing and airtime are added to propagation latency.
20. Frontend bootstrap and remaining requirements
frontend/ is bootstrapped from git@git.naori.cloud:thebadking/vue-template.git (Vue 3, Vite, TypeScript, UnoCSS, Supabase Auth/storage). It includes Socket.IO scenario configuration, Three.js orbit/zoom rendering, backend-provided trajectories, a fixed-height terminal telemetry/event log with scrollback, and a Supabase simulation_runs migration with owner-scoped RLS. The client renders backend state without local physics or prediction. Keep Interception Stats by Projectile below other statistics when Monte Carlo results are exposed. Terrain, antenna patterns, drone airframe models, field-calibrated device profiles, and additional detailed renderer requirements remain future work.
21. Implemented library boundary (2026-10-03)
SciPy >=1.14 provides independent DOP853 references and attitude conversions. Stone Soup provides position-measurement Kalman tracking and bearing-only IR EKF correction; raw Doppler is retained without inventing transverse velocity. The reduced default drone model remains a kinematic surrogate, with exact first-order actuator decay and realized bounded-velocity displacement, rather than the full rotor model described in section 6. Optional RotorPy 2.1 supplies the Crazyflie reference rotor model, and optional JSBSim supplies explicitly selected aircraft models with normalized open-loop controls. RotorPy's deterministic ODE path avoids the library's global RNG motor-noise draws and is constrained to the tested 2.1 API. Both adapters use SI/NED boundaries and declared reference model provenance. Examples are not calibration for deployed equipment.
The atmosphere implements standard geopotential lapse-rate layers through 86 km geometric altitude; higher altitude fails validation rather than silently clamping. Source: U.S. Standard Atmosphere, 1976. Flat terrain and straight swept segments remain approximations; analytic and step-size tests delimit numerical accuracy. Above-atmosphere flight, reentry thermodynamics, accurate Mach-dependent aero, spatial turbulence, uncertain platform attitude and clutter/data association remain model extensions requiring data and independent validation.
Live standby and path visualization follow-up (2026-10-03)
First delivered radar position detection requests vertical standby takeoff for every available defensive drone, independently of velocity observability and assignment reachability. The frontend exposes early_takeoff_enabled (default true) and standby_altitude_m (default 150 m, range (0, 3000]). Commands incur radio queue/airtime/loss/latency and retry at one-second intervals, at most three attempts. Received assignments supersede standby without resetting airborne ascent height. Standby aircraft hold their launch-site horizontal position and remain assignable. Late standby packets cannot overwrite an active assignment. On threat termination, airborne standby aircraft hold altitude; automatic landing and battery endurance are outside this change.
Live snapshots include flight_phase, standby_altitude_m, intended_trajectory_ned_m, and intention_kind=delivered_command_reference. Intention previews use onboard position estimates, reference speed/rate limits and the configured altitude curve, with a 60 s horizon and 1 s sample interval; they do not claim a force-based physical prediction. Actual trajectories retain 1,800 samples at the default 0.2 s recording cadence and capture terminal endpoints between samples. The scene differentiates faint attacker truth, persistent radar evidence, estimated attacker forecasts, dashed drone intentions and solid actual drone paths.