1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| import numpy as np from typing import Tuple
def model_chest_displacement( breathing_rate: float = 0.25, breathing_amplitude: float = 4e-3, heart_rate: float = 1.2, heart_amplitude: float = 0.5e-3, duration_s: float = 10.0, fs: float = 1000.0 ) -> Tuple[np.ndarray, np.ndarray]: """ 模拟胸部位移(呼吸+心跳) 参考: RT-VSS论文中的Blender生理建模 Args: breathing_rate: 呼吸频率(Hz) breathing_amplitude: 呼吸幅度(m), 正常4-12mm heart_rate: 心率(Hz) heart_amplitude: 心跳幅度(m), 正常0.2-0.5mm duration_s: 持续时间 fs: 采样率 Returns: (t, displacement): 时间轴和胸部位移 """ t = np.linspace(0, duration_s, int(duration_s * fs)) breathing = breathing_amplitude * np.sin(2 * np.pi * breathing_rate * t) heartbeat = heart_amplitude * ( np.sin(2 * np.pi * heart_rate * t) + 0.3 * np.sin(4 * np.pi * heart_rate * t) ) displacement = breathing + heartbeat return t, displacement
def simulate_fr3_radar_sensing( displacement: np.ndarray, carrier_freq_ghz: float = 10.0, bandwidth_ghz: float = 2.0, n_rx_positions: int = 10, fs: float = 1000.0 ) -> dict: """ 模拟FR3频段雷达感知 Args: displacement: 胸部位移 carrier_freq_ghz: 载波频率 bandwidth_ghz: 带宽 n_rx_positions: 接收位置数 fs: 采样率 Returns: 检测结果 """ c = 3e8 wavelength = c / (carrier_freq_ghz * 1e9) phase_change = 4 * np.pi * displacement / wavelength results = [] for rx_idx in range(n_rx_positions): multipath_delay = np.random.uniform(0, 50e-9, 5) multipath_amp = np.random.uniform(0.1, 0.5, 5) rx_signal = np.exp(1j * phase_change) for d, a in zip(multipath_delay, multipath_amp): rx_signal += a * np.exp(1j * (phase_change + 2 * np.pi * carrier_freq_ghz * 1e9 * d)) phase_extracted = np.unwrap(np.angle(rx_signal)) from scipy.signal import butter, filtfilt b_resp, a_resp = butter(4, [0.1, 0.5], btype='band', fs=fs) breathing_signal = filtfilt(b_resp, a_resp, phase_extracted) b_heart, a_heart = butter(4, [0.8, 2.0], btype='band', fs=fs) heart_signal = filtfilt(b_heart, a_heart, phase_extracted) from scipy.signal import welch f_resp, psd_resp = welch(breathing_signal, fs=fs, nperseg=1024) f_heart, psd_heart = welch(heart_signal, fs=fs, nperseg=1024) breathing_rate_est = f_resp[np.argmax(psd_resp)] * 60 heart_rate_est = f_heart[np.argmax(psd_heart)] * 60 results.append({ 'rx_position': rx_idx, 'breathing_rate_bpm': breathing_rate_est, 'heart_rate_bpm': heart_rate_est, 'snr_db': 10 * np.log10(np.max(psd_resp) / np.mean(psd_resp)) }) return { 'carrier_freq_ghz': carrier_freq_ghz, 'wavelength_mm': wavelength * 1000, 'results': results }
if __name__ == "__main__": print("=== RT-VSS FR3频段生命体征感知仿真 ===\n") t, disp = model_chest_displacement( breathing_rate=0.25, heart_rate=1.2, duration_s=10.0 ) print(f"呼吸幅度: {np.max(disp)*1000:.2f} mm") print(f"载波波长(FR3@10GHz): {3e8/10e9*1000:.1f} mm") print(f"相位变化范围: ±{4*np.pi*np.max(disp)/(3e8/10e9):.4f} rad") print("\n[FR3 - 10 GHz]") result_fr3 = simulate_fr3_radar_sensing(disp, carrier_freq_ghz=10.0) for r in result_fr3['results'][:3]: print(f" RX{r['rx_position']}: 呼吸={r['breathing_rate_bpm']:.1f} BPM, " f"心率={r['heart_rate_bpm']:.1f} BPM, SNR={r['snr_db']:.1f} dB") print("\n[FR1 - 3.5 GHz]") result_fr1 = simulate_fr3_radar_sensing(disp, carrier_freq_ghz=3.5) for r in result_fr1['results'][:3]: print(f" RX{r['rx_position']}: 呼吸={r['breathing_rate_bpm']:.1f} BPM, " f"心率={r['heart_rate_bpm']:.1f} BPM, SNR={r['snr_db']:.1f} dB") print("\n[FR2 - 28 GHz]") result_fr2 = simulate_fr3_radar_sensing(disp, carrier_freq_ghz=28.0) for r in result_fr2['results'][:3]: print(f" RX{r['rx_position']}: 呼吸={r['breathing_rate_bpm']:.1f} BPM, " f"心率={r['heart_rate_bpm']:.1f} BPM, SNR={r['snr_db']:.1f} dB")
|