/ 8_Utils / Python / CSV_radar.py
CSV_radar.py
  1  import numpy as np
  2  import pandas as pd
  3  import math
  4  
  5  def generate_radar_csv(filename="pulse_compression_output.csv"):
  6      """
  7      Generate realistic radar CSV data for testing the Python GUI
  8      """
  9      
 10      # Radar parameters matching your testbench
 11      num_long_chirps = 16
 12      num_short_chirps = 16
 13      samples_per_chirp = 512  # Reduced for manageable file size
 14      fs_adc = 400e6  # 400 MHz ADC
 15      timestamp_ns = 0
 16      
 17      # Target parameters
 18      targets = [
 19          {'range': 3000, 'velocity': 25, 'snr': 30, 'azimuth': 10, 'elevation': 5},   # Fast moving target
 20          {'range': 5000, 'velocity': -15, 'snr': 25, 'azimuth': 20, 'elevation': 2},  # Approaching target
 21          {'range': 8000, 'velocity': 5, 'snr': 20, 'azimuth': 30, 'elevation': 8},    # Slow moving target
 22          {'range': 12000, 'velocity': -8, 'snr': 18, 'azimuth': 45, 'elevation': 3},  # Distant target
 23      ]
 24      
 25      # Noise parameters
 26      noise_std = 5
 27      clutter_std = 10
 28      
 29      data = []
 30      chirp_number = 0
 31      
 32      # Generate Long Chirps (30µs duration equivalent)
 33      print("Generating Long Chirps...")
 34      for chirp in range(num_long_chirps):
 35          for sample in range(samples_per_chirp):
 36              # Base noise
 37              i_val = np.random.normal(0, noise_std)
 38              q_val = np.random.normal(0, noise_std)
 39              
 40              # Add clutter (stationary targets)
 41              clutter_range = 2000  # Fixed clutter at 2km
 42              if sample < 100:  # Simulate clutter in first 100 samples
 43                  i_val += np.random.normal(0, clutter_std)
 44                  q_val += np.random.normal(0, clutter_std)
 45              
 46              # Add moving targets with Doppler shift
 47              for target in targets:
 48                  # Calculate range bin (simplified)
 49                  range_bin = int(target['range'] / 20)  # ~20m per bin
 50                  doppler_phase = 2 * math.pi * target['velocity'] * chirp / 100  # Doppler phase shift
 51                  
 52                  # Target appears around its range bin with some spread
 53                  if abs(sample - range_bin) < 10:
 54                      # Signal amplitude decreases with range
 55                      amplitude = target['snr'] * (10000 / target['range'])
 56                      phase = 2 * math.pi * sample / 50 + doppler_phase
 57                      
 58                      i_val += amplitude * math.cos(phase)
 59                      q_val += amplitude * math.sin(phase)
 60              
 61              # Calculate derived values
 62              magnitude_squared = i_val**2 + q_val**2
 63              
 64              data.append({
 65                  'timestamp_ns': timestamp_ns,
 66                  'chirp_number': chirp_number,
 67                  'chirp_type': 'LONG',
 68                  'sample_index': sample,
 69                  'I_value': int(i_val),
 70                  'Q_value': int(q_val),
 71                  'magnitude_squared': int(magnitude_squared)
 72              })
 73              
 74              timestamp_ns += int(1e9 / fs_adc)  # 2.5ns per sample at 400MHz
 75          
 76          chirp_number += 1
 77          timestamp_ns += 137000  # Add listening period (137µs)
 78      
 79      # Guard time between long and short chirps
 80      timestamp_ns += 175400  # 175.4µs guard time
 81      
 82      # Generate Short Chirps (0.5µs duration equivalent)
 83      print("Generating Short Chirps...")
 84      for chirp in range(num_short_chirps):
 85          for sample in range(samples_per_chirp):
 86              # Base noise
 87              i_val = np.random.normal(0, noise_std)
 88              q_val = np.random.normal(0, noise_std)
 89              
 90              # Add clutter (different characteristics for short chirps)
 91              if sample < 50:  # Less clutter for short chirps
 92                  i_val += np.random.normal(0, clutter_std/2)
 93                  q_val += np.random.normal(0, clutter_std/2)
 94              
 95              # Add moving targets with different Doppler for short chirps
 96              for target in targets:
 97                  # Range bin calculation (different for short chirps)
 98                  range_bin = int(target['range'] / 40)  # Different range resolution
 99                  doppler_phase = 2 * math.pi * target['velocity'] * (chirp + 5) / 80  # Different Doppler
100                  
101                  # Target appears around its range bin
102                  if abs(sample - range_bin) < 8:
103                      # Different amplitude characteristics for short chirps
104                      amplitude = target['snr'] * 0.7 * (8000 / target['range'])  # 70% amplitude
105                      phase = 2 * math.pi * sample / 30 + doppler_phase
106                      
107                      i_val += amplitude * math.cos(phase)
108                      q_val += amplitude * math.sin(phase)
109              
110              # Calculate derived values
111              magnitude_squared = i_val**2 + q_val**2
112              
113              data.append({
114                  'timestamp_ns': timestamp_ns,
115                  'chirp_number': chirp_number,
116                  'chirp_type': 'SHORT',
117                  'sample_index': sample,
118                  'I_value': int(i_val),
119                  'Q_value': int(q_val),
120                  'magnitude_squared': int(magnitude_squared)
121              })
122              
123              timestamp_ns += int(1e9 / fs_adc)  # 2.5ns per sample
124          
125          chirp_number += 1
126          timestamp_ns += 174500  # Add listening period (174.5µs)
127      
128      # Create DataFrame
129      df = pd.DataFrame(data)
130      
131      # Save to CSV
132      df.to_csv(filename, index=False)
133      print(f"Generated CSV file: {filename}")
134      print(f"Total samples: {len(df)}")
135      print(f"Long chirps: {num_long_chirps}, Short chirps: {num_short_chirps}")
136      print(f"Samples per chirp: {samples_per_chirp}")
137      print(f"File size: {len(df) // 1000}K samples")
138      
139      return df
140  
141  def analyze_generated_data(df):
142      """
143      Analyze the generated data to verify target detection
144      """
145      print("\n=== Data Analysis ===")
146      
147      # Basic statistics
148      long_chirps = df[df['chirp_type'] == 'LONG']
149      short_chirps = df[df['chirp_type'] == 'SHORT']
150      
151      print(f"Long chirp samples: {len(long_chirps)}")
152      print(f"Short chirp samples: {len(short_chirps)}")
153      print(f"Unique chirp numbers: {df['chirp_number'].nunique()}")
154      
155      # Calculate actual magnitude and phase for analysis
156      df['magnitude'] = np.sqrt(df['I_value']**2 + df['Q_value']**2)
157      df['phase_rad'] = np.arctan2(df['Q_value'], df['I_value'])
158      
159      # Find high-magnitude samples (potential targets)
160      high_mag_threshold = df['magnitude'].quantile(0.95)  # Top 5%
161      targets_detected = df[df['magnitude'] > high_mag_threshold]
162      
163      print(f"\nTarget detection threshold: {high_mag_threshold:.2f}")
164      print(f"High magnitude samples: {len(targets_detected)}")
165      
166      # Group by chirp type
167      long_targets = targets_detected[targets_detected['chirp_type'] == 'LONG']
168      short_targets = targets_detected[targets_detected['chirp_type'] == 'SHORT']
169      
170      print(f"Targets in long chirps: {len(long_targets)}")
171      print(f"Targets in short chirps: {len(short_targets)}")
172      
173      return df
174  
175  if __name__ == "__main__":
176      # Generate the CSV file
177      df = generate_radar_csv("test_radar_data.csv")
178      
179      # Analyze the generated data
180      analyze_generated_data(df)
181      
182      print("\n=== CSV File Ready ===")
183      print("You can now test the Python GUI with this CSV file!")
184      print("The file contains:")
185      print("- 16 Long chirps + 16 Short chirps")
186      print("- 4 simulated targets at different ranges and velocities")
187      print("- Realistic noise and clutter")
188      print("- Proper I/Q data for Doppler processing")