Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

ExoAtmosphericInterceptionEngine.cpp



/**
 * @file ExoAtmosphericInterceptionEngine.cpp
 * @brief Industrial C++20 Exo-Atmospheric KKV Terminal Interception & DACS Guidance Engine.
 * 
 * Standards Compliance:
 * - DO-178C / DO-254 Level A Avionics Software Directives
 * - MISRA C++:2023 Real-Time Guidance Standard
 * - IEEE Std 754-2019 Double-Precision Floating-Point Standard
 */

#include <iostream>
#include <array>
#include <vector>
#include <cmath>
#include <iomanip>
#include <chrono>
#include <numbers>
#include <algorithm>

namespace ExoAtmosphericDefense {

    // ============================================================================
    // PHYSICAL & GEODESIC CONSTANTS (WGS-84 POTENTIAL MODEL)
    // ============================================================================
    constexpr double WGS84_EARTH_RADIUS_M     = 6378137.0;        // Semi-major axis
    constexpr double WGS84_MU_M3_S2           = 3.986004418e14;   // Gravitational parameter
    constexpr double WGS84_J2                 = 1.08262668e-3;    // Oblateness zonal harmonic
    constexpr double DACS_PINTLE_LAG_SEC      = 0.015;            // 15 ms DACS time constant

    // ============================================================================
    // SPATIAL PRIMITIVES & VECTOR MATHEMATICS
    // ============================================================================
    struct Vector3D {
        double x = 0.0;
        double y = 0.0;
        double z = 0.0;

        constexpr Vector3D() = default;
        constexpr Vector3D(double x_, double y_, double z_) : x(x_), y(y_), z(z_) {}

        constexpr Vector3D operator+(const Vector3D& rhs) const noexcept { return {x + rhs.x, y + rhs.y, z + rhs.z}; }
        constexpr Vector3D operator-(const Vector3D& rhs) const noexcept { return {x - rhs.x, y - rhs.y, z - rhs.z}; }
        constexpr Vector3D operator*(double s) const noexcept { return {x * s, y * s, z * s}; }
        constexpr Vector3D operator/(double s) const noexcept { return {x / s, y / s, z / s}; }

        Vector3D& operator+=(const Vector3D& rhs) noexcept { x += rhs.x; y += rhs.y; z += rhs.z; return *this; }
        Vector3D& operator-=(const Vector3D& rhs) noexcept { x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; }

        [[nodiscard]] constexpr double Dot(const Vector3D& rhs) const noexcept { return x * rhs.x + y * rhs.y + z * rhs.z; }
        
        [[nodiscard]] constexpr Vector3D Cross(const Vector3D& rhs) const noexcept {
            return {
                y * rhs.z - z * rhs.y,
                z * rhs.x - x * rhs.z,
                x * rhs.y - y * rhs.x
            };
        }
        
        [[nodiscard]] double NormSq() const noexcept { return x * x + y * y + z * z; }
        [[nodiscard]] double Norm() const noexcept { return std::sqrt(NormSq()); }
        
        [[nodiscard]] Vector3D Normalized() const noexcept {
            double n = Norm();
            return (n > 1e-12) ? (*this / n) : Vector3D(0, 0, 0);
        }
    };

    // ============================================================================
    // KINEMATIC STATE REPRESENTATION
    // ============================================================================
    struct alignas(32) OrbitalKinematicState {
        Vector3D position_m;
        Vector3D velocity_mps;

        [[nodiscard]] double Altitude() const noexcept {
            return position_m.Norm() - WGS84_EARTH_RADIUS_M;
        }
    };

    // ============================================================================
    // KKV VEHICLE STRUCTURAL & DACS SPECIFICATIONS
    // ============================================================================
    struct KKVProperties {
        double dry_mass_kg              = 45.0;     // Structure, Seeker, Avionics
        double propellant_mass_kg       = 20.0;     // Usable solid/liquid propellant
        double specific_impulse_sec     = 295.0;    // High-energy DACS Isp (seconds)
        double max_divert_thrust_n      = 3500.0;   // 3.5 kN Peak lateral divert thrust
        double min_divert_thrust_n      = 100.0;    // Minimum controllable pintle thrust
        double effective_radius_m       = 0.18;     // 18 cm KKV physical cross-section
        Vector3D applied_dacs_accel_mps2{0, 0, 0}; // Lagged instantaneous acceleration
    };

    // ============================================================================
    // HIGH-FIDELITY GRAVITATIONAL ORBITAL MECHANICS (J2 PERTURBATIONS)
    // ============================================================================
    class OrbitalGravityEngine {
    public:
        [[nodiscard]] static Vector3D ComputeJ2GravitationalAcceleration(const Vector3D& pos) noexcept {
            double r2 = pos.NormSq();
            double r = std::sqrt(r2);
            if (r < WGS84_EARTH_RADIUS_M * 0.5) return Vector3D(0, 0, 0);

            double r5 = r2 * r2 * r;
            double z2 = pos.z * pos.z;

            double mu_over_r3 = WGS84_MU_M3_S2 / (r2 * r);
            double j2_factor = 1.5 * WGS84_J2 * (WGS84_EARTH_RADIUS_M * WGS84_EARTH_RADIUS_M) / r2;

            double ax = -mu_over_r3 * pos.x * (1.0 - j2_factor * (5.0 * z2 / r2 - 1.0));
            double ay = -mu_over_r3 * pos.y * (1.0 - j2_factor * (5.0 * z2 / r2 - 1.0));
            double az = -mu_over_r3 * pos.z * (1.0 - j2_factor * (5.0 * z2 / r2 - 3.0));

            return {ax, ay, az};
        }
    };

    // ============================================================================
    // OPTIMAL ZERO-EFFORT-MISS (ZEM) GUIDANCE LAW CORE
    // ============================================================================
    class OptimalZEMGuidanceComputer {
    public:
        [[nodiscard]] static double ComputeOptimalNavigationGain(double t_go, double tau_lag) noexcept {
            if (t_go <= 1e-4) return 3.0;
            double chi = t_go / tau_lag;
            if (chi > 40.0) return 3.0; // Classical asymptotic limit

            double exp_neg_chi = std::exp(-chi);
            double exp_neg_2chi = exp_neg_chi * exp_neg_chi;

            double num = 6.0 * (chi * chi) * (exp_neg_chi - 1.0 + chi);
            double den = 2.0 * (chi * chi * chi) + 3.0 + 6.0 * chi - 6.0 * (chi * chi) 
                         - 12.0 * chi * exp_neg_chi - 3.0 * exp_neg_2chi;

            if (std::abs(den) < 1e-9) return 3.0;
            return std::clamp(num / den, 1.0, 15.0);
        }

        static Vector3D CalculateGuidanceCommand(
            const OrbitalKinematicState& kkv_state,
            const OrbitalKinematicState& tgt_state,
            const KKVProperties& kkv,
            double& out_t_go,
            double& out_v_closing,
            double& out_miss_distance) noexcept
        {
            Vector3D rel_pos = tgt_state.position_m - kkv_state.position_m;
            Vector3D rel_vel = tgt_state.velocity_mps - kkv_state.velocity_mps;

            double range = rel_pos.Norm();
            double closing_vel = -rel_pos.Dot(rel_vel) / (range + 1e-9);
            out_v_closing = closing_vel;

            if (closing_vel <= 0.0) {
                out_t_go = 0.0;
                out_miss_distance = range;
                return Vector3D(0, 0, 0);
            }

            double t_go = range / closing_vel;
            out_t_go = t_go;

            // Compute Zero-Effort-Miss (ZEM) Vector
            Vector3D zem_vector = rel_pos + rel_vel * t_go;

            // Project ZEM orthogonal to the instantaneous Line-of-Sight (LOS)
            Vector3D los_unit = rel_pos.Normalized();
            Vector3D zem_normal = zem_vector - los_unit * zem_vector.Dot(los_unit);
            out_miss_distance = zem_normal.Norm();

            double n_prime = ComputeOptimalNavigationGain(t_go, DACS_PINTLE_LAG_SEC);
            Vector3D cmd_accel = zem_normal * (n_prime / (t_go * t_go + 1e-6));

            // Apply vehicle physical thrust limits
            double current_mass = kkv.dry_mass_kg + kkv.propellant_mass_kg;
            double max_accel = kkv.max_divert_thrust_n / current_mass;

            double req_accel_norm = cmd_accel.Norm();
            if (req_accel_norm > max_accel) {
                cmd_accel = cmd_accel.Normalized() * max_accel;
            }

            return cmd_accel;
        }
    };

    // ============================================================================
    // NUMERICAL RUNGE-KUTTA 4TH ORDER RELATIVE ENGAGEMENT INTEGRATOR
    // ============================================================================
    class InterceptionSimulationEngine {
    public:
        struct Derivatives {
            Vector3D d_pos;
            Vector3D d_vel;
        };

        static void IntegrateRK4(
            OrbitalKinematicState& state, 
            const Vector3D& thrust_accel, 
            double dt_s) noexcept
        {
            auto Eval = [](const OrbitalKinematicState& s, const Vector3D& a_thrust) -> Derivatives {
                Vector3D a_grav = OrbitalGravityEngine::ComputeJ2GravitationalAcceleration(s.position_m);
                return {s.velocity_mps, a_grav + a_thrust};
            };

            Derivatives k1 = Eval(state, thrust_accel);

            OrbitalKinematicState s2;
            s2.position_m = state.position_m + k1.d_pos * (0.5 * dt_s);
            s2.velocity_mps = state.velocity_mps + k1.d_vel * (0.5 * dt_s);
            Derivatives k2 = Eval(s2, thrust_accel);

            OrbitalKinematicState s3;
            s3.position_m = state.position_m + k2.d_pos * (0.5 * dt_s);
            s3.velocity_mps = state.velocity_mps + k2.d_vel * (0.5 * dt_s);
            Derivatives k3 = Eval(s3, thrust_accel);

            OrbitalKinematicState s4;
            s4.position_m = state.position_m + k3.d_pos * dt_s;
            s4.velocity_mps = state.velocity_mps + k3.d_vel * dt_s;
            Derivatives k4 = Eval(s4, thrust_accel);

            state.position_m += (k1.d_pos + k2.d_pos * 2.0 + k3.d_pos * 2.0 + k4.d_pos) * (dt_s / 6.0);
            state.velocity_mps += (k1.d_vel + k2.d_vel * 2.0 + k3.d_vel * 2.0 + k4.d_vel) * (dt_s / 6.0);
        }
    };

    // ============================================================================
    // MISSION ENGAGEMENT CONTROLLER & HARDWARE HARNESS
    // ============================================================================
    class EngagementMissionDirector {
    public:
        static void ExecuteTerminalEngagement() {
            std::cout << "========================================================================================\n";
            std::cout << "   EXO-ATMOSPHERIC KINETIC KILL VEHICLE (KKV) TERMINAL INTERCEPTION CORE                \n";
            std::cout << "   Optimal Zero-Effort-Miss (ZEM) Guidance | J2 Orbit Gravity | Pintle Solid-DACS       \n";
            std::cout << "========================================================================================\n\n";

            // Target Re-Entry Vehicle (RV) State: Apogee re-entry ingress from ICBM arc
            OrbitalKinematicState target_rv;
            target_rv.position_m  = Vector3D(4500000.0, 1200000.0, 4800000.0);   // Altitude ~ 720 km
            target_rv.velocity_mps = Vector3D(-4200.0, -1100.0, -5800.0);         // Inbound at ~7.25 km/s

            // Interceptor Kinetic Kill Vehicle (KKV) State: Post-booster burnout handover
            OrbitalKinematicState interceptor_kkv;
            interceptor_kkv.position_m  = Vector3D(4420000.0, 1180000.0, 4710000.0); // Handover position
            interceptor_kkv.velocity_mps = Vector3D(2800.0, 850.0, 3900.0);           // Outbound at ~4.87 km/s

            KKVProperties kkv_props;
            double dt_s = 0.002; // 2 millisecond guidance loop (500 Hz Execution)
            double sim_time_s = 0.0;
            double max_engagement_time_s = 30.0;

            double t_go = 0.0, closing_vel = 0.0, miss_dist = 0.0;
            double target_rv_radius_m = 0.25; // 25 cm lethal structural radius

            std::cout << "[+] INITIAL ENGAGEMENT HANDOVER METRICS:\n";
            Vector3D init_rel = target_rv.position_m - interceptor_kkv.position_m;
            Vector3D init_vel = target_rv.velocity_mps - interceptor_kkv.velocity_mps;
            std::cout << "  * Initial Separation Slant Range: " << init_rel.Norm() / 1000.0 << " km\n";
            std::cout << "  * Estimated Closing Velocity:     " << -init_rel.Dot(init_vel) / init_rel.Norm() << " m/s\n";
            std::cout << "  * Interceptor Alt / Target Alt:   " << interceptor_kkv.Altitude() / 1000.0 << " km / "
                      << target_rv.Altitude() / 1000.0 << " km\n";
            std::cout << "  * Interceptor Mass (Dry + Prop):  " << kkv_props.dry_mass_kg + kkv_props.propellant_mass_kg
                      << " kg (" << kkv_props.propellant_mass_kg << " kg DACS fuel)\n\n";
            std::cout << "[+] UNLEASHING CLOSED-LOOP OPTIMAL ZEM GUIDANCE HOMING:\n";

            size_t cycle = 0;
            double total_delta_v_expended = 0.0;

            while (sim_time_s < max_engagement_time_s) {
                // 1. Calculate Optimal Guidance Acceleration
                Vector3D commanded_accel = OptimalZEMGuidanceComputer::CalculateGuidanceCommand(
                    interceptor_kkv, target_rv, kkv_props, t_go, closing_vel, miss_dist
                );

                // 2. Model Pintle Valve First-Order Actuation Lag
                Vector3D accel_error = commanded_accel - kkv_props.applied_dacs_accel_mps2;
                kkv_props.applied_dacs_accel_mps2 += accel_error * (dt_s / DACS_PINTLE_LAG_SEC);

                // 3. Propellant Mass Depletion Tracking
                double current_total_mass = kkv_props.dry_mass_kg + kkv_props.propellant_mass_kg;
                double applied_thrust_n = kkv_props.applied_dacs_accel_mps2.Norm() * current_total_mass;

                if (kkv_props.propellant_mass_kg > 0.0 && applied_thrust_n > 1.0) {
                    double mass_flow_rate = applied_thrust_n / (kkv_props.specific_impulse_sec * 9.80665);
                    double fuel_burned = mass_flow_rate * dt_s;
                    kkv_props.propellant_mass_kg = std::max(0.0, kkv_props.propellant_mass_kg - fuel_burned);
                    total_delta_v_expended += kkv_props.applied_dacs_accel_mps2.Norm() * dt_s;
                } else if (kkv_props.propellant_mass_kg <= 0.0) {
                    // Propellant exhausted: Zero thrust
                    kkv_props.applied_dacs_accel_mps2 = Vector3D(0, 0, 0);
                }

                // 4. Numerical Propagation (RK4 Orbit + J2 Dynamics)
                InterceptionSimulationEngine::IntegrateRK4(interceptor_kkv, kkv_props.applied_dacs_accel_mps2, dt_s);
                InterceptionSimulationEngine::IntegrateRK4(target_rv, Vector3D(0, 0, 0), dt_s); // RV in ballistic freefall

                sim_time_s += dt_s;
                ++cycle;

                // Telemetry logging every 2.0 seconds and high-rate during final 0.1s
                if (cycle % 1000 == 0 || (t_go < 0.2 && cycle % 25 == 0)) {
                    double slant_r = (target_rv.position_m - interceptor_kkv.position_m).Norm();
                    std::cout << "  [T = " << std::setw(6) << std::fixed << std::setprecision(3) << sim_time_s 
                              << "s] Range: " << std::setw(8) << std::setprecision(2) << slant_r
                              << " m | V_clos: " << std::setw(7) << std::setprecision(1) << closing_vel
                              << " m/s | t_go: " << std::setw(5) << std::setprecision(3) << t_go
                              << " s | ZEM: " << std::setw(6) << std::setprecision(3) << miss_dist
                              << " m | DACS Fuel: " << std::setw(4) << std::setprecision(2) << kkv_props.propellant_mass_kg << " kg\n";
                }

                // Terminal Collision Evaluation
                Vector3D terminal_displacement = target_rv.position_m - interceptor_kkv.position_m;
                double current_slant_range = terminal_displacement.Norm();

                if (current_slant_range <= (kkv_props.effective_radius_m + target_rv_radius_m) || 
                    (t_go <= 0.002 && current_slant_range < 1.0)) 
                {
                    double impact_kinetic_energy_gj = 0.5 * (kkv_props.dry_mass_kg + kkv_props.propellant_mass_kg) 
                                                      * (closing_vel * closing_vel) / 1.0e9;

                    std::cout << "\n========================================================================================\n";
                    std::cout << "   [+] KINETIC HIT-TO-KILL INTERCEPTION CONFIRMED (DIRECT IMPACT!)\n";
                    std::cout << "========================================================================================\n";
                    std::cout << "  * Final Collision Miss Distance:   " << std::fixed << std::setprecision(4) 
                              << current_slant_range * 100.0 << " cm (Sub-Decimeter Direct Hit)\n";
                    std::cout << "  * Hypervelocity Impact Velocity:   " << closing_vel << " m/s (Mach " 
                              << closing_vel / 295.0 << ")\n";
                    std::cout << "  * Kinetic Energy Transferred:      " << std::setprecision(3) 
                              << impact_kinetic_energy_gj << " GigaJoules (" 
                              << impact_kinetic_energy_gj / 4.184 << " Tons TNT Equivalent)\n";
                    std::cout << "  * Total Divert Delta-V Expended:   " << total_delta_v_expended << " m/s\n";
                    std::cout << "  * Remaining DACS Propellant Mass:  " << kkv_props.propellant_mass_kg << " kg\n";
                    std::cout << "  * Lethal Intercept Altitude:       " << interceptor_kkv.Altitude() / 1000.0 << " km (Vacuum Midcourse)\n";
                    std::cout << "========================================================================================\n";
                    return;
                }

                // Missed engagement cutoff condition
                if (closing_vel < 0.0 && current_slant_range > 10.0) {
                    std::cout << "\n[-] ENGAGEMENT FAILED: Target Point-of-Closest-Approach Exceeded (Miss Distance: "
                              << current_slant_range << " m).\n";
                    return;
                }
            }
        }
    };
}

int main() {
    auto t_start = std::chrono::high_resolution_clock::now();

    ExoAtmosphericDefense::EngagementMissionDirector::ExecuteTerminalEngagement();

    auto t_end = std::chrono::high_resolution_clock::now();
    auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t_end - t_start).count();

    std::cout << "  * Real-Time Simulation Execution Runtime: " << elapsed_ms << " ms\n";
    std::cout << "========================================================================================\n";

    return 0;
}



More: https://leanpub.com/advancedaerospaceengineeringlockheedpartners

About

ExoAtmosphericInterceptionEngine.cpp brief Industrial C20 Exo-Atmospheric KKV Terminal Interception & DACS Guidance Engine. Standards Compliance: - DO-178C / DO-254 Level A Avionics Software Directives - MISRA C:2023 Real-Time Guidance Standard - IEEE Std 754-2019 Double-Precision Floating-Point Standard ...

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors