Real-time collision avoidance for 50 satellites navigating 10,000+ debris objects in Low Earth Orbit.
J2-perturbed DOP853 orbital propagation | 4-stage KDTree conjunction assessment | RTN-frame evasion planning | Tsiolkovsky fuel tracking | 60 FPS operational dashboard
Technical Report (PDF) | Video Demo (link TBD)
git clone https://github.com/SarmaHighOnCode/acm-orbital.git
cd acm-orbital
docker compose build --no-cache
docker compose upWait for AUTO_SEED | Complete — dashboard ready in the terminal (~60 seconds), then open http://localhost:8000.
The engine automatically seeds 50 satellites + 10,000 debris objects and runs 5 simulation steps so the dashboard is fully populated on first load — no manual setup required.
# Backend
cd backend
pip install -r requirements.txt
python -m uvicorn main:app --host 0.0.0.0 --port 8000
# Frontend (separate terminal)
cd frontend
npm ci && npm run devcurl http://localhost:8000/health
# {"status":"healthy","service":"acm-orbital","engine_initialized":true}How our implementation maps to each scoring category:
| Requirement | Implementation | Location |
|---|---|---|
| Collision detection | 4-stage filter: altitude band (kills 85% debris) → KDTree spatial index → Brent TCA refinement → CDM emission | backend/engine/collision.py |
| Conjunction threshold | 100 m hard threshold with 200 m safety margin for early warning | backend/config.py:CONJUNCTION_THRESHOLD_KM |
| Autonomous evasion | CRITICAL/RED CDMs trigger automatic evasion + recovery burn sequences | backend/engine/simulation.py:_auto_plan_evasion() |
| Instantaneous scan | Separate KDTree scan at current positions catches inter-step collisions | backend/engine/collision.py:check_collisions() |
| 24-hour lookahead | CDM prediction window spans full 24h via DOP853 dense output | backend/engine/collision.py:assess() |
| Impulsive burn model | Velocity-only delta-v application, no position displacement during burn | backend/engine/simulation.py:_execute_maneuvers() |
| Requirement | Implementation | Location |
|---|---|---|
| Tsiolkovsky tracking | Mass-aware exponential fuel depletion: dm = m * (1 - exp(-dv / (Isp * g0))) |
backend/engine/fuel_tracker.py |
| T-axis priority | Burns prioritized along transverse axis (most fuel-efficient for phasing) | backend/engine/maneuver_planner.py |
| 36-point optimizer | Searches 3h window in 5-min steps for minimum-dv burn time | backend/engine/maneuver_planner.py:plan_evasion() |
| 15 m/s burn cap | Hard reject for user burns; auto-split with 610s spacing for planned burns | backend/engine/maneuver_planner.py, fuel_tracker.py |
| EOL graveyard | Hohmann deorbit at 2.5 kg fuel (5% threshold) prevents uncontrolled debris | backend/engine/simulation.py:_check_eol() |
| Recovery burns | Every evasion paired with Clohessy-Wiltshire recovery to nominal slot | backend/engine/maneuver_planner.py:plan_recovery() |
| Requirement | Implementation | Location |
|---|---|---|
| Station-keeping box | 10 km radius nominal slot tracking per satellite | backend/config.py:STATION_KEEPING_RADIUS_KM |
| Uptime scoring | Continuous time-outside-box tracking with exponential decay penalty | backend/engine/simulation.py:_check_station_keeping() |
| Fast recovery | Recovery burn scheduled when debris exceeds 50 km separation | backend/engine/maneuver_planner.py |
| Nominal drift prevention | Satellites re-checked for slot deviation after each propagation step | backend/engine/simulation.py |
| Benchmark | Target | Achieved | How |
|---|---|---|---|
| 100K debris ingest | < 5 s | ~2 s | Vectorized NumPy array packing |
| KDTree build (100K) | < 3 s | < 100 ms | SciPy cKDTree |
| 50 queries into 100K | < 1 s | < 1 ms | Ball-point spatial query |
| Batch propagation (15K) | < 30 s | PASS | Single 6N-dimensional DOP853 call |
| Full tick (50 sats x 10K) | < 120 s | ~10 s | 4-stage filter eliminates 85% before indexing |
| Sub-O(N^2) proof | Required | Verified | Doubling D increases time < 2x (log scaling) |
All six required visualization modules at 60 FPS:
| Module | Spec Requirement | Implementation | Location |
|---|---|---|---|
| Ground Track Map | Mercator 2D projection (default view) | Canvas equirectangular with satellite markers, 90-min trails, predicted trajectories, terminator line, debris cloud, 6 ground stations, continental outlines | frontend/src/components/GroundTrack.jsx |
| 3D Globe | Optional enhancement | Three.js WebGL globe with day/night lighting, GMST rotation, city lights, sun-position tracking | frontend/src/components/GlobeView.jsx |
| Bullseye Plot | Polar conjunction chart | Canvas polar chart: radial = TCA, color = risk level (GREEN/YELLOW/RED/CRITICAL), pulsing animation | frontend/src/components/BullseyePlot.jsx |
| Fuel Heatmap | Per-satellite fuel gauges | Sorted bar gauges with gradient coloring, fleet status counters, click-to-select | frontend/src/components/FuelHeatmap.jsx |
| Delta-V Chart | Fuel consumed vs collisions avoided | XY area chart with gradient fill, cumulative tracking | frontend/src/components/DeltaVChart.jsx |
| Maneuver Timeline | Gantt-style burn schedule | Per-satellite rows with burn blocks, 600s cooldown periods, blackout zone flagging, CDM markers, cooldown violations | frontend/src/components/ManeuverTimeline.jsx |
Additional: 2D/3D view toggle, click-to-select satellite across all panels, Zustand state management with 2s polling.
| Aspect | Evidence |
|---|---|
| Architecture | 3-layer separation: Physics Engine (pure Python, zero HTTP) → API Layer (FastAPI + Pydantic) → Frontend (React + Canvas) |
| Single source of truth | All 16 physical constants frozen in backend/config.py |
| Type safety | Pydantic request/response schemas with strict validation |
| Test suite | 1,163 pytest-collected tests across 30 files (all passing) |
| Structured logging | structlog with JSON output for distributed tracing |
| No O(N^2) | Architectural invariant enforced across all modules |
| Configuration | backend/config.py imported everywhere, no magic numbers |
+---------------------------+
| React 18 Dashboard |
| Canvas 2D + Three.js 3D |
| Zustand State Store |
+------------+--------------+
| HTTP/JSON (2s polling)
+------------+--------------+
| FastAPI + Pydantic |
| 4 REST endpoints |
| orjson serialization |
+------------+--------------+
| Python calls
+----------+-----------+-----------+----------+
| | | | |
Propagator Collision Maneuver Fuel Ground
(DOP853) (KDTree) Planner Tracker Stations
(RTN) (Tsiolkovsky) (LOS)
| Layer | Technology | Lines of Code |
|---|---|---|
| Physics Engine | Python 3.11 + NumPy + SciPy | 2,787 |
| API Layer | FastAPI + Pydantic + orjson | 450 |
| Frontend | React 18 + Canvas + Three.js + Zustand | 2,655 |
| Tests | pytest | 18,000 |
| Total | ~35,000 |
Ingest ECI state vectors for satellites and debris.
curl -X POST http://localhost:8000/api/telemetry \
-H "Content-Type: application/json" \
-d '{
"timestamp": "2026-03-01T12:00:00Z",
"objects": [{
"id": "SAT-01", "type": "SATELLITE",
"r": {"x": 7000, "y": 0, "z": 0},
"v": {"x": 0, "y": 7.546, "z": 0}
}]
}'Response: {"status": "ACK", "processed_count": 1, "active_cdm_warnings": 0}
Schedule evasion/recovery burn sequences with full constraint validation.
curl -X POST http://localhost:8000/api/maneuver/schedule \
-H "Content-Type: application/json" \
-d '{
"satelliteId": "SAT-01",
"maneuver_sequence": [{
"burn_id": "EVA-001",
"burnTime": "2026-03-01T12:30:00Z",
"deltaV_vector": {"x": 0.005, "y": 0, "z": 0}
}]
}'Response: {"status": "SCHEDULED", "validation": {"ground_station_los": true, "sufficient_fuel": true, "projected_mass_remaining_kg": 548.2}}
Advance simulation by N seconds with full physics pipeline.
curl -X POST http://localhost:8000/api/simulate/step \
-H "Content-Type: application/json" \
-d '{"step_seconds": 600}'Response: {"status": "STEP_COMPLETE", "new_timestamp": "...", "collisions_detected": 0, "maneuvers_executed": 2}
Compressed frontend state: satellites, CDMs, debris cloud, maneuver log.
curl http://localhost:8000/api/visualization/snapshotContainer health check.
acm-orbital/
Dockerfile # Single-container ubuntu:22.04 build
docker-compose.yml # Local dev convenience
backend/
main.py # FastAPI app + lifespan + auto-step loop
config.py # 16 physical constants (single source of truth)
schemas.py # Pydantic API contracts
api/
telemetry.py # POST /api/telemetry
simulate.py # POST /api/simulate/step
maneuver.py # POST /api/maneuver/schedule
visualization.py # GET /api/visualization/snapshot
engine/
propagator.py # J2-perturbed DOP853 batch propagation
collision.py # 4-stage KDTree conjunction assessment
maneuver_planner.py # RTN-frame evasion + recovery burns
fuel_tracker.py # Tsiolkovsky mass depletion
ground_stations.py # LOS elevation + ECEF/ECI transforms
simulation.py # 7-stage tick orchestrator
models.py # Satellite/Debris data classes
data/
ground_stations.csv # 6 stations (Bengaluru, Svalbard, Goldstone, Punta Arenas, IIT Delhi, McMurdo)
tests/ # 258 tests across 21 files
frontend/
src/
App.jsx # Root + 2s snapshot polling
store.js # Zustand global state
components/
Dashboard.jsx # 6-panel grid with 2D/3D toggle
GroundTrack.jsx # 2D Mercator ground track (default)
GlobeView.jsx # 3D Three.js globe with day/night
BullseyePlot.jsx # Polar conjunction proximity chart
FuelHeatmap.jsx # Fleet fuel gauges
DeltaVChart.jsx # Fuel vs collisions avoided
ManeuverTimeline.jsx # Gantt burn timeline with blackouts
utils/
api.js # Snapshot fetcher with retry
coordinates.js # ECI/geodetic transforms
docs/
technical_report.tex # LaTeX source
ACM_Technical_Report.pdf # Compiled 15-page report
1,163 tests collected | all passing | 30 test files
cd backend && python -m pytest tests/ -q| Category | Tests | What it validates |
|---|---|---|
| Core physics engine | 76 | J2 propagation, collision detection, fuel tracking, RTN burns, tick loop |
| Stress and flood | 47 | 100K debris ingest, KDTree scaling, ground station LOS, Tsiolkovsky precision |
| End-to-end integration | 31 | Full API + engine pipelines, CDM lifecycle, evasion sequences |
| Adversarial judge vectors | 20 | Burn timing edge cases, GMST accuracy, fast-path drift bounds |
| Extreme boundary cases | 16 | Numerical edge cases, near-zero fuel, simultaneous threats |
| System stress tests | 15 | Fleet wipeout recovery, race conditions, 50K snapshot serialization |
| Parametric sweeps | 100+ | Coverage gap audits, breaking audit vectors, chaos invariants |
| Unit tests | 850+ | Individual module validation across all engine components |
12 critical physics bugs discovered during development, all fixed with dedicated regression tests. Full details in the Technical Report.
Orbital Propagation — J2-perturbed two-body dynamics integrated via DOP853 (8th-order Dormand-Prince, adaptive step-size). Vectorized batch: all N objects packed into a single 6N-dimensional ODE call. Energy conservation < 0.05% over 50 orbital periods.
Conjunction Assessment — Four-stage filter cascade reducing O(S*D) to O(S log D):
- Altitude band pre-filter eliminates ~85% of debris
- cKDTree spatial index with 200 km search radius
- Brent's method TCA refinement on DOP853 dense polynomial
- CDM emission with risk classification (CRITICAL/RED/YELLOW/GREEN)
Maneuver Planning — RTN orbital frame with T-axis priority for fuel efficiency. 36-point burn time search over 3-hour window. Paired evasion + Clohessy-Wiltshire recovery burns. LOS blackout guard with bidirectional rescheduling.
Fuel Tracking — Tsiolkovsky rocket equation with mass-aware depletion. EOL graveyard deorbit at 5% fuel threshold via Hohmann transfer.
- Base image:
ubuntu:22.04(as required) - Port:
8000bound to0.0.0.0 - Single container: Frontend Vite build copied to
backend/static/, served by FastAPI - Auto-seed: 50 satellites + 10,000 debris populated on startup
- Auto-step: Background loop advances simulation 100s every 2s
- Health check:
GET /healthfor container orchestration
| Deliverable | Status | Location |
|---|---|---|
| Source code (GitHub) | Complete | This repository |
| Dockerfile (ubuntu:22.04) | Complete | ./Dockerfile |
| Technical Report (PDF) | Complete | docs/ACM_Technical_Report.pdf |
| Video Demo (< 5 min) | Pending | Link TBD |
Built at IIT Delhi for the National Space Hackathon 2026.