雷达信号处理 python实现(二)相干与非相干积累 带宽与分辨率的关系
第七章(相干/非相干积累)与第八章(带宽与分辨率)的所有理论仿真:
第七章 覆盖内容:
| 公式 | 可视化 | 物理验证 |
|---|---|---|
| (1.28) 单脉冲SNR | 单脉冲信号波形 | SNR=1 (0dB)基准 |
| (1.29-1.30) 相干积累 | SNR改善曲线(10logN) | 64脉冲→18dB增益 |
| (1.31-1.32) 多普勒影响 | 积累损失vs多普勒频移 | 展示失配损失 |
| (1.33) 非相干积累 | 相干vs非相干对比 | 64脉冲→9dB增益(√N) |
第八章 覆盖内容:
| 公式 | 可视化 | 物理验证 |
|---|---|---|
| (1.34) 尺度变换 | 时域压缩↔频域展宽 | 高斯脉冲4倍压缩演示 |
| (1.35) 脉冲压缩 | LFM脉压结果 | 10μs/50MHz信号→3m分辨率 |
| 综合指标 | 时宽带宽积TB=500 | 分辨率改善500倍对比 |
🚀 使用方法
bash
# 安装依赖 pip install numpy matplotlib scipy # 运行仿真 python radar_ch7_ch8_simulation.py # 输出结果 # - 控制台: 6条理论验证结论 # - 图像文件: radar_ch7_ch8_simulation.png (12子图)脚本包含完整中文注释,可直接用于教学演示或实验报告
完整仿真脚本
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 雷达信号处理仿真 - 第七章:相干/非相干积累 & 第八章:带宽与分辨率 版本: 1.0 功能: 实现公式(1.28-1.35)的完整仿真与可视化 """ import numpy as np import matplotlib.pyplot as plt from scipy import signal import warnings warnings.filterwarnings('ignore') # 设置中文字体 plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans'] plt.rcParams['axes.unicode_minus'] = False def main(): print("="*70) print("雷达信号处理仿真 - 第七章:相干/非相干积累 & 第八章:带宽与分辨率") print("="*70) # ==================== 参数设置 ==================== c = 3e8 # 光速 N_pulse = 64 # 积累脉冲数 A = 1.0 # 信号幅度 sigma_w = 1.0 # 噪声标准差 chi_1 = A**2 / (sigma_w**2) # 公式(1.28): 单脉冲SNR print(f"【仿真参数】积累脉冲数 N={N_pulse}, 单脉冲SNR χ₁={chi_1:.2f}dB\n") fig = plt.figure(figsize=(20, 16)) # ==================== 第七章:相干与非相干积累 ==================== print("█ 第七章:相干与非相干积累") print("-"*50) np.random.seed(42) phi = np.pi / 4 # 初始相位 # 7.1 单脉冲SNR验证 ax1 = plt.subplot(4, 3, 1) single_pulse = A * np.exp(1j * phi) + (sigma_w/np.sqrt(2)) * (np.random.randn(1000) + 1j*np.random.randn(1000)) ax1.plot(np.real(single_pulse[:100]), label='信号+噪声', alpha=0.7) ax1.axhline(y=A*np.cos(phi), color='r', linestyle='--', label=f'信号实部={A*np.cos(phi):.2f}') ax1.set_xlabel('采样点') ax1.set_ylabel('幅度') ax1.set_title(f'7.1 单脉冲接收信号 (理论SNR={chi_1:.1f}dB)', fontweight='bold') ax1.legend(fontsize=9) ax1.grid(True, alpha=0.3) # 7.2/7.3 相干积累增益 ax2 = plt.subplot(4, 3, 2) N_coherent = np.arange(1, N_pulse+1) coherent_gain_dB = 10 * np.log10(N_coherent) ax2.plot(N_coherent, coherent_gain_dB, 'b-', linewidth=2.5, label='理论: 10·log₁₀(N)') ax2.scatter([1, 16, 64], [0, 12, 18], color='red', s=50, zorder=5) ax2.set_xlabel('积累脉冲数 N') ax2.set_ylabel('SNR改善 (dB)') ax2.set_title('7.3 相干积累增益: χₙ = N·χ₁', fontweight='bold') ax2.grid(True, alpha=0.3) ax2.legend() # 7.2 相干积累过程 ax3 = plt.subplot(4, 3, 3) N_demo = 16 pulses = [A * np.exp(1j * phi) + (sigma_w/np.sqrt(2)) * (np.random.randn() + 1j*np.random.randn()) for _ in range(N_demo)] accumulated = np.cumsum(pulses) snr_progress = np.abs(accumulated)**2 / (np.arange(1, N_demo+1) * sigma_w**2) ax3.plot(range(1, N_demo+1), 10*np.log10(snr_progress/chi_1), 'g-o', linewidth=2) ax3.plot(range(1, N_demo+1), 10*np.log10(np.arange(1, N_demo+1)), 'r--', linewidth=2, label='理论曲线') ax3.set_xlabel('积累脉冲数') ax3.set_ylabel('SNR改善倍数 (dB)') ax3.set_title('7.2 相干积累过程演示 (电压同相相加)', fontweight='bold') ax3.legend() ax3.grid(True, alpha=0.3) print(f" 7.3 相干积累: {N_pulse}脉冲提供{10*np.log10(N_pulse):.1f}dB增益") # 7.4 多普勒频移影响 ax4 = plt.subplot(4, 3, 4) N_doppler = 32 fd_range = np.linspace(0, 0.5, 100) loss_uncomp = [] for f in fd_range: signal_sum = np.abs(np.sum(np.exp(1j * 2 * np.pi * f * np.arange(N_doppler)))) loss_uncomp.append((signal_sum/N_doppler)**2) loss_uncomp = np.array(loss_uncomp) ax4.plot(fd_range, 10*np.log10(loss_uncomp + 1e-10), 'b-', linewidth=2.5, label='无多普勒补偿') ax4.axhline(y=0, color='r', linestyle='--', label='有补偿(理论值)') ax4.set_xlabel('归一化多普勒频率 fₐ·Tᵣ') ax4.set_ylabel('积累增益损失 (dB)') ax4.set_title(f'7.4 多普勒频移对相干积累的影响 (N={N_doppler})', fontweight='bold') ax4.legend() ax4.grid(True, alpha=0.3) # 7.5 非相干积累对比 ax5 = plt.subplot(4, 3, 5) N_incoh = np.arange(1, N_pulse+1) ax5.plot(N_incoh, 10*np.log10(N_incoh), 'b-', linewidth=2.5, label='相干积累 (10logN)') ax5.plot(N_incoh, 10*np.log10(np.sqrt(N_incoh)), 'r--', linewidth=2.5, label='非相干积累 (5logN)') ax5.set_xlabel('积累脉冲数 N') ax5.set_ylabel('SNR改善 (dB)') ax5.set_title('7.5 非相干积累增益对比 (幅度平方相加)', fontweight='bold') ax5.legend() ax5.grid(True, alpha=0.3) print(f" 7.5 非相干积累: {N_pulse}脉冲提供约{5*np.log10(N_pulse):.1f}dB增益 (SNR∝√N)") # ==================== 第八章:带宽与分辨率 ==================== print("\n█ 第八章:带宽与分辨率") print("-"*50) # 8.1 时频尺度变换 ax7 = plt.subplot(4, 3, 7) t = np.linspace(-5, 5, 1000) pulse1 = np.exp(-(t/2.0)**2) # 宽脉冲 pulse2 = np.exp(-(t/0.5)**2) # 窄脉冲 (压缩) ax7.plot(t, pulse1, 'b-', linewidth=2, label='宽脉冲 τ=2.0μs') ax7.plot(t, pulse2, 'r-', linewidth=2, label='窄脉冲 τ=0.5μs') ax7.set_xlabel('时间 (μs)') ax7.set_ylabel('归一化幅度') ax7.set_title('8.1 时域尺度变换 (时域压缩→脉宽减小)', fontweight='bold') ax7.legend() ax7.grid(True, alpha=0.3) # 8.1 频域对应 ax8 = plt.subplot(4, 3, 8) dt = t[1] - t[0] freq = np.fft.fftshift(np.fft.fftfreq(len(t), dt)) X1 = np.abs(np.fft.fftshift(np.fft.fft(pulse1))) X2 = np.abs(np.fft.fftshift(np.fft.fft(pulse2))) ax8.plot(freq, X1/np.max(X1), 'b-', linewidth=2, label='宽脉冲谱 (窄带)') ax8.plot(freq, X2/np.max(X2), 'r-', linewidth=2, label='窄脉冲谱 (宽带)') ax8.set_xlabel('频率 (MHz)') ax8.set_ylabel('归一化幅度') ax8.set_title('8.1 频域尺度变换 (时域压缩→频域展宽)', fontweight='bold') ax8.legend() ax8.grid(True, alpha=0.3) ax8.set_xlim([-2, 2]) print(" 8.1 尺度变换: 时域压缩4倍 → 频域展宽4倍") # 8.2 脉冲压缩 ax9 = plt.subplot(4, 3, 9) T = 10e-6 # 10μs脉宽 B = 50e6 # 50MHz带宽 K = B / T Fs = 10*B t_pc = np.linspace(0, T, int(Fs*T)) lfm = np.exp(1j * np.pi * K * (t_pc - T/2)**2) compressed = np.convolve(lfm, np.conj(lfm[::-1]), mode='full') compressed = compressed / np.max(np.abs(compressed)) t_comp = np.linspace(-T, T, len(compressed)) ax9.plot(t_comp*1e6, 20*np.log10(np.abs(compressed) + 1e-10), 'b-', linewidth=2) ax9.axhline(y=-3, color='r', linestyle='--', alpha=0.7, label='-3dB线') ax9.set_xlabel('时间 (μs)') ax9.set_ylabel('归一化功率 (dB)') ax9.set_title(f'8.2 脉冲压缩结果 (T={T*1e6}μs, B={B/1e6}MHz)', fontweight='bold') ax9.legend() ax9.grid(True, alpha=0.3) ax9.set_ylim([-40, 5]) # 8.2 分辨率对比 ax10 = plt.subplot(4, 3, 10) res_before = c * T / 2 res_after = c / (2 * B) bars = ax10.bar(['脉压前\n(普通脉冲)', '脉压后\n(脉冲压缩)'], [res_before, res_after], color=['gray', 'green'], alpha=0.7) ax10.set_ylabel('距离分辨率 (m)') ax10.set_title('8.2 脉冲压缩距离分辨率对比 (ΔR = c/(2B))', fontweight='bold') for bar, res in zip(bars, [res_before, res_after]): ax10.text(bar.get_x() + bar.get_width()/2., bar.get_height(), f'{res:.1f}m', ha='center', va='bottom', fontweight='bold') ax10.grid(True, alpha=0.3, axis='y') TBWP = B * T print(f" 8.2 脉冲压缩: 时宽带宽积T·B={TBWP:.0f}, 分辨率改善{TBWP:.0f}倍") print(f" 脉压前: {res_before:.1f}m → 脉压后: {res_after:.1f}m") # 8.2 性能指标 ax11 = plt.subplot(4, 3, 11) ax11.text(0.5, 0.6, f'时宽带宽积\nT·B = {TBWP:.0f}', fontsize=24, ha='center', va='center', bbox=dict(boxstyle='round,pad=0.5', facecolor='lightblue', alpha=0.5)) ax11.text(0.5, 0.3, f'脉冲压缩比 = {TBWP:.0f}', fontsize=16, ha='center', va='center') ax11.text(0.5, 0.15, f'距离分辨率改善{TBWP:.0f}倍', fontsize=14, ha='center', va='center', color='red') ax11.set_xlim([0, 1]) ax11.set_ylim([0, 1]) ax11.axis('off') ax11.set_title('8.2 脉冲压缩性能指标', fontweight='bold') # 综合对比 ax12 = plt.subplot(4, 3, 12) N_range = np.arange(1, 129) ax12.plot(N_range, 21-10*np.log10(N_range), 'b-', linewidth=2.5, label='相干积累后所需SNR') ax12.plot(N_range, 21-5*np.log10(N_range), 'r--', linewidth=2.5, label='非相干积累后所需SNR') ax12.set_xlabel('积累脉冲数 N') ax12.set_ylabel('所需信噪比 (dB)') ax12.set_title('积累技术对比:达到PD=90%所需SNR', fontweight='bold') ax12.legend() ax12.grid(True, alpha=0.3) plt.tight_layout() plt.savefig('radar_ch7_ch8_simulation.png', dpi=150, bbox_inches='tight') print("\n" + "="*70) print("仿真完成!结果已保存为 radar_ch7_ch8_simulation.png") print("="*70) plt.show() if __name__ == "__main__": main()