|
| 1 | +import numpy as np |
| 2 | +import matplotlib.pyplot as plt |
| 3 | + |
| 4 | +class RadarInstance: |
| 5 | + def __init__(self, range_max=100, fov=90): |
| 6 | + self.range_max = range_max |
| 7 | + self.fov = fov # Field of View in degrees |
| 8 | + self.targets = [] |
| 9 | + |
| 10 | + def add_target(self, distance, angle, velocity, rcs): |
| 11 | + """ |
| 12 | + RCS = Radar Cross Section (how 'visible' the object is) |
| 13 | + """ |
| 14 | + self.targets.append({ |
| 15 | + 'dist': distance, |
| 16 | + 'angle': np.radians(angle), |
| 17 | + 'vel': velocity, |
| 18 | + 'rcs': rcs |
| 19 | + }) |
| 20 | + |
| 21 | + def simulate_scan(self, noise_level=0.1): |
| 22 | + """Simulates raw sensor data with Gaussian noise.""" |
| 23 | + detections = [] |
| 24 | + for t in self.targets: |
| 25 | + # Signal Strength calculation based on Inverse Square Law |
| 26 | + signal_strength = t['rcs'] / (t['dist']**2) |
| 27 | + if signal_strength > noise_level: |
| 28 | + # Add synthetic noise to the reading |
| 29 | + detected_dist = t['dist'] + np.random.normal(0, 0.5) |
| 30 | + detections.append([detected_dist, t['angle'], t['vel']]) |
| 31 | + return np.array(detections) |
| 32 | + |
| 33 | +# --- Instance Initialization --- |
| 34 | +radar_unit = RadarInstance() |
| 35 | +radar_unit.add_target(distance=65, angle=30, velocity=250, rcs=1.5) # Fast Jet |
| 36 | +radar_unit.add_target(distance=30, angle=-15, velocity=15, rcs=0.5) # Drone |
| 37 | + |
| 38 | + |
| 39 | + |
| 40 | +def classify_target(velocity, rcs): |
| 41 | + """Simple AI heuristic for target identification.""" |
| 42 | + if velocity > 200: |
| 43 | + return "STRIKE_AIRCRAFT", "HIGH" |
| 44 | + elif velocity > 50 and rcs < 0.2: |
| 45 | + return "STEALTH_UAV", "CRITICAL" |
| 46 | + elif velocity < 20: |
| 47 | + return "STATIC_OBSTACLE", "LOW" |
| 48 | + else: |
| 49 | + return "UNKNOWN", "MEDIUM" |
| 50 | + |
| 51 | + |
| 52 | + |
| 53 | +def render_hud(detections): |
| 54 | + fig = plt.figure(figsize=(8, 8), facecolor='black') |
| 55 | + ax = fig.add_subplot(111, polar=True) |
| 56 | + ax.set_facecolor('#001100') |
| 57 | + |
| 58 | + # HUD Styling |
| 59 | + ax.tick_params(colors='lime') |
| 60 | + ax.grid(color='lime', alpha=0.3) |
| 61 | + |
| 62 | + if len(detections) > 0: |
| 63 | + dist = detections[:, 0] |
| 64 | + angles = detections[:, 1] |
| 65 | + vels = detections[:, 2] |
| 66 | + |
| 67 | + for i in range(len(dist)): |
| 68 | + label, threat = classify_target(vels[i], 1.0) |
| 69 | + ax.scatter(angles[i], dist[i], color='red', s=100, marker='x') |
| 70 | + ax.text(angles[i], dist[i]+5, f"{label}\n{vels[i]}m/s", |
| 71 | + color='lime', fontsize=9, fontweight='bold') |
| 72 | + |
| 73 | + ax.set_ylim(0, 100) |
| 74 | + plt.title("AI RADAR INSTANCE v1.0 - ACTIVE SCAN", color='lime', pad=20) |
| 75 | + plt.show() |
| 76 | + |
| 77 | +# Execute Scan |
| 78 | +data = radar_unit.simulate_scan() |
| 79 | +render_hud(data) |
| 80 | + |
| 81 | + |
| 82 | + |
| 83 | +import numpy as np |
| 84 | +from scipy import signal |
| 85 | + |
| 86 | +def get_micro_doppler_signature(raw_signal, fs=1000): |
| 87 | + """ |
| 88 | + Converts 1D Radar signal into a 2D Time-Frequency Spectrogram. |
| 89 | + This 'image' is what the AI actually 'sees'. |
| 90 | + """ |
| 91 | + frequencies, times, spectrogram = signal.spectrogram( |
| 92 | + raw_signal, fs, nperseg=64, noverlap=32, return_onesided=True |
| 93 | + ) |
| 94 | + # Log scale for better AI feature extraction |
| 95 | + return 10 * np.log10(spectrogram + 1e-10) |
| 96 | + |
| 97 | + |
| 98 | + |
| 99 | + |
| 100 | +from tensorflow.keras import layers, models |
| 101 | + |
| 102 | +def build_advanced_radar_ai(): |
| 103 | + model = models.Sequential([ |
| 104 | + # Input: (Frames, Height, Width, Channels) |
| 105 | + layers.Input(shape=(10, 64, 64, 1)), |
| 106 | + |
| 107 | + # Spatial-Temporal Feature Extraction |
| 108 | + layers.ConvLSTM2D(32, (3, 3), padding='same', return_sequences=False, activation='relu'), |
| 109 | + layers.BatchNormalization(), |
| 110 | + |
| 111 | + layers.Flatten(), |
| 112 | + layers.Dense(128, activation='relu'), |
| 113 | + layers.Dropout(0.3), |
| 114 | + layers.Dense(4, activation='softmax') # [DRONE, BIRD, PERSON, VEHICLE] |
| 115 | + ]) |
| 116 | + model.compile(optimizer='adam', loss='categorical_crossentropy') |
| 117 | + return model |
| 118 | + |
| 119 | +radar_classifier = build_advanced_radar_ai() |
| 120 | + |
| 121 | + |
| 122 | + |
| 123 | +class KalmanTracker: |
| 124 | + def __init__(self, dt=0.1): |
| 125 | + # State: [pos_x, pos_y, vel_x, vel_y] |
| 126 | + self.x = np.zeros((4, 1)) |
| 127 | + # Transition Matrix |
| 128 | + self.F = np.array([[1, 0, dt, 0], |
| 129 | + [0, 1, 0, dt], |
| 130 | + [0, 0, 1, 0], |
| 131 | + [0, 0, 0, 1]]) |
| 132 | + # Measurement Matrix (we only measure position) |
| 133 | + self.H = np.array([[1, 0, 0, 0], |
| 134 | + [0, 1, 0, 0]]) |
| 135 | + self.P = np.eye(4) * 100 # Uncertainty |
| 136 | + self.R = np.eye(2) * 1 # Measurement Noise |
| 137 | + |
| 138 | + def predict(self): |
| 139 | + self.x = np.dot(self.F, self.x) |
| 140 | + self.P = np.dot(np.dot(self.F, self.P), self.F.T) |
| 141 | + return self.x |
| 142 | + |
| 143 | + def update(self, z): |
| 144 | + # Kalman Gain |
| 145 | + S = np.dot(self.H, np.dot(self.P, self.H.T)) + self.R |
| 146 | + K = np.dot(np.dot(self.P, self.H.T), np.linalg.inv(S)) |
| 147 | + # Update State |
| 148 | + y = z - np.dot(self.H, self.x) |
| 149 | + self.x = self.x + np.dot(K, y) |
| 150 | + self.P = self.P - np.dot(np.dot(K, self.H), self.P) |
| 151 | + |
| 152 | + |
| 153 | + |
| 154 | +# Initialization |
| 155 | +tracker = KalmanTracker() |
| 156 | +# ... (simulate incoming radar data stream) ... |
| 157 | + |
| 158 | +def process_frame(raw_iq_data): |
| 159 | + # 1. AI Classification |
| 160 | + spec = get_micro_doppler_signature(raw_iq_data) |
| 161 | + # prediction = radar_classifier.predict(spec) |
| 162 | + |
| 163 | + # 2. State Estimation (Tracking) |
| 164 | + # Assume z is [detected_x, detected_y] |
| 165 | + z = np.array([[50.5], [20.2]]) |
| 166 | + tracker.update(z) |
| 167 | + future_state = tracker.predict() |
| 168 | + |
| 169 | + return { |
| 170 | + "id": "TGT-01", |
| 171 | + "class": "STRIKE_UAV", |
| 172 | + "pos": (future_state[0,0], future_state[1,0]), |
| 173 | + "vel": (future_state[2,0], future_state[3,0]) |
| 174 | + } |
0 commit comments