Files
KG-access 3c05d2be09 1. SNR 신호처리, Secondary surface 영향 고려하여 SNR 재계산
2. Coverage Figure 개선
3. 윈도우 생성 및 성능 계산 함수 추가
2026-03-06 06:48:07 +09:00

308 lines
16 KiB
Matlab

% =========================================================================
% Tx_Main.m
% Pure MATLAB FMCW TX Simulator (Multi-Chirp Frame Generation)
% =========================================================================
clear; clc; close all;
% =============== 경로 추가 및 환경설정 ===============
currentFilePath = mfilename('fullpath');
currentFolder = fileparts(currentFilePath);
addpath(genpath(currentFolder));
%% =================== 시각화 토글 ===================
% 각 figure를 개별적으로 on/off 할 수 있습니다.
PlotToggle.range_profile = false; % Step 8 Range Profile
PlotToggle.tx_single = false; % Figure 1 Single chirp waveform
PlotToggle.tx_multi = false; % Figure 2 Multi chirp waveform
PlotToggle.tx_antenna = false; % Figure 3 TX antenna pattern
PlotToggle.rx_antenna = false; % Figure 4 RX antenna pattern
PlotToggle.rd_map = false; % Figure 5 Range-Doppler map
PlotToggle.cfar = false; % Figure 6 CFAR detections
PlotToggle.coverage = true; % Figure 7 Coverage analysis
%% =================== 파라미터 입력 ===================
% 1) 기본 물리 파라미터
RadarParams.Basic.c = 3e8; % 빛의 속도 (m/s)
RadarParams.Basic.kb = physconst('Boltzmann'); % 볼츠만 상수
RadarParams.Basic.T0 = 290; % 표준 온도 (K)
% 2) 파형생성 관련 파라미터
RadarParams.Waveform.fc = 77e9; % 중심 주파수 (Hz)
RadarParams.Waveform.lambda_c = RadarParams.Basic.c / RadarParams.Waveform.fc; % 중심 파장 (m)
RadarParams.Waveform.NumChirps = 128; % 프레임당 처프 수
RadarParams.Waveform.B_valid = 1e9; % 유효 대역폭 (Hz)
RadarParams.Waveform.fs_adc = 10e6; % ADC 샘플링 주파수 (Hz)
RadarParams.Waveform.fs_waveform = 1e6; % 파형 시각화용 샘플링 주파수 (Hz)
% 2-1) 처프 타이밍 파라미터
RadarParams.Waveform.Timing.IdleTime = 7e-6; % 처프 아이들 구간 (s)
RadarParams.Waveform.Timing.TxStartTime = 1e-6; % Tx on (s)
RadarParams.Waveform.Timing.AdcStartTime = 6e-6; % ADC on (s)
RadarParams.Waveform.Timing.AdcSampTime = 50e-6; % ADC 샘플링 구간 (s)
RadarParams.Waveform.Timing.ExcessTime = 1e-6; % 램프 끝나고 다음 처프 시작까지의 여유 시간 (s)
RadarParams.Waveform.Timing.RampEndTime = RadarParams.Waveform.Timing.IdleTime + RadarParams.Waveform.Timing.TxStartTime + RadarParams.Waveform.Timing.AdcSampTime + RadarParams.Waveform.Timing.ExcessTime; % 램프 종료 시점 (s)
RadarParams.Waveform.PRI = RadarParams.Waveform.Timing.IdleTime + RadarParams.Waveform.Timing.RampEndTime; % Pulse Repetition Interval (s)
RadarParams.Waveform.PRF = 1 / RadarParams.Waveform.PRI; % Pulse Repetition Frequency (Hz)
RadarParams.Waveform.Slope = RadarParams.Waveform.B_valid / RadarParams.Waveform.Timing.AdcSampTime; % 처프의 주파수 상승률 (Hz/s)
RadarParams.Waveform.f_start = RadarParams.Waveform.fc - RadarParams.Waveform.B_valid/2; % 처프 시작 주파수 (Hz)
% 2-2) Phase noise & nonlinearity parameters
RadarParams.Waveform.nonideal.pn_level = 0.05; % 위상노이즈 레벨
RadarParams.Waveform.nonideal.f_ripple = 300e3; % 위상 리플 주파수
RadarParams.Waveform.nonideal.peak_phase_error = 0.1; % 최대 위상오차
RadarParams.Waveform.nonideal.power_drop_edge = 0.8; % 엣지 파워 드롭
RadarParams.Waveform.nonideal.enable_phase_noise = true; % phase noise on/off
RadarParams.Waveform.nonideal.enable_nonlinearity = false; % nonlinearity on/off
% Datasheet 기반 phase noise 설정 (예: -89 dBc/Hz @ 1 MHz)
RadarParams.Waveform.nonideal.phaseNoise.offset_Hz = [1e6];
RadarParams.Waveform.nonideal.phaseNoise.level_dBc_Hz = [-89];
% 2-3) MIMO 모드 설정
RadarParams.Waveform.mimoMode = 'TDM'; % 'TDM' 또는 'DDMA'
% 3) RF 출력 파라미터 - 주파수별 출력 파워 [dBm]
RadarParams.RFOutput.PA_Profile.freqs = [76e9, 76.5e9, 77e9, 77.5e9, 78e9, 79e9];
RadarParams.RFOutput.PA_Profile.power_dBm = [10.5, 11.5, 12.0, 11.5, 10.5, 8.0];
% 4) 안테나 파라미터
% 4-1) 안테나 개수 및 위치 (3xN 행렬, 단위: m)
RadarParams.Antenna.NumTx = 2;
RadarParams.Antenna.NumRx = 4;
RadarParams.Antenna.lambda = RadarParams.Waveform.lambda_c;
RadarParams.Antenna.TxPos = [ (0:RadarParams.Antenna.NumTx-1)*2*RadarParams.Antenna.lambda; zeros(1,RadarParams.Antenna.NumTx); zeros(1,RadarParams.Antenna.NumTx) ]; % 3xNumTx
RadarParams.Antenna.RxPos = [ (0:RadarParams.Antenna.NumRx-1)*0.5*RadarParams.Antenna.lambda; zeros(1,RadarParams.Antenna.NumRx); zeros(1,RadarParams.Antenna.NumRx) ]; % 3xNumRx
% 4-2) 안테나 패턴 (각각 NumTx, NumRx 길이의 구조체 배열)
RadarParams.Antenna.tx_files = {}; % 필요시 파일명 지정 (로드 기능)
RadarParams.Antenna.rx_files = {};
RadarParams.Antenna.TxPattern = build_antenna_patterns(RadarParams.Antenna.NumTx, '1D', 12, 5, 30, 10, RadarParams.Antenna.tx_files);
RadarParams.Antenna.RxPattern = build_antenna_patterns(RadarParams.Antenna.NumRx, '2D', 14, 2, 40, 15, RadarParams.Antenna.rx_files);
% 5) 타겟 모델링
RadarParams.Target.R = [12]; % 타겟 거리 (m)
RadarParams.Target.v = [7]; % 타겟 속도 (m/s)
RadarParams.Target.rcs = [-10000]; % 타겟 RCS (dBsm)
RadarParams.Target.az = [10]; % 방위각 (deg)
RadarParams.Target.el = [0]; % 고각 (deg)
RadarParams.Target.NumTargets = length(RadarParams.Target.R);
% 6) 수신단 파라미터
RadarParams.Rxpath.fc_hpf = 1400; % HPF 컷오프 (Hz)
RadarParams.Rxpath.fc_lpf = 0.8*RadarParams.Waveform.fs_adc/2; % LPF 컷오프 주파수 (Hz)
RadarParams.Rxpath.adc_bits = 12; % ADC 비트수
RadarParams.Rxpath.adc_v_full_scale = 2.0; % full-scale 전압 (Vp-p)
RadarParams.Rxpath.receiver_mode = 'Real'; % 'IQ' 또는 'Real'
RadarParams.Rxpath.load_impedance_ohm = 50; % 임피던스 (Ohm)
RadarParams.Rxpath.rxPathGain_dB = 50; % RX 경로 이득 (dB)
RadarParams.Rxpath.system_NF_dB = 15; % 시스템 잡음지수 (dB)
% 6-5) Spur parameters (하드웨어 스퍼 모델링)
% Spur의 원인은 다양하지만, 대표적으로 LO leakage, 믹서 비선형성, ADC 샘플링 톤, 스위칭 잡음 등이 있다.
% SpurParams 구조체는 각 스퍼 유형별로 존재 여부와 특성을 정의한다.
% 실제에서는 spur의 발생 위치는 다양하지만, 시뮬레이션에서는 수신단에서 spur 신호를 모사하기 때문에 apply_lna_and_mixer 함수 내에서 SpurParams를 참조하여 spur 신호를 생성하고 adc_combined에 추가하는 방식으로 구현.
RadarParams.SpurParams = struct();
RadarParams.SpurParams.lo = struct('amp',0.01,'freq',1e6); % 위상 성분
RadarParams.SpurParams.mixer= struct('alpha2',1e-4,'alpha3',1e-6); % 2/3차 비선형
RadarParams.SpurParams.adc = struct('amp',1e-3,'freq',2e6); % ADC 이후 톤
RadarParams.SpurParams.switch = struct('amp',5e-4,'freq',500e3); % 스위칭 잡음
RadarParams.SpurParams.pulse = struct('amp',0.0,'freq',200e3,'duty',0.1,'phase',0);% 펄스열 락킹
RadarParams.SpurParams.lo_leak = struct('amp',0.05); % DC/LO leakage
RadarParams.SpurParams.clip = struct('amp',0.03,'range',20); % Clipping spur
RadarParams.SpurParams.enabled = false; % spur on/off
% 7) 신호처리 파라미터
RadarParams.SP.RDM.window_type_range = 'hann'; % Range FFT용 윈도우
RadarParams.SP.RDM.window_type_doppler = 'chebwin'; % Doppler FFT용 윈도우
num_samples_range = round(RadarParams.Waveform.fs_adc * RadarParams.Waveform.Timing.AdcSampTime);
num_chirps_doppler = RadarParams.Waveform.NumChirps;
% Range 윈도우 생성 및 성능 지표 계산
[RadarParams.SP.RDM.window_range, RadarParams.SP.RDM.window_metrics_range] = ...
create_window_with_metrics(RadarParams.SP.RDM.window_type_range, num_samples_range, 60);
% Doppler 윈도우 생성 및 성능 지표 계산
[RadarParams.SP.RDM.window_doppler, RadarParams.SP.RDM.window_metrics_doppler] = ...
create_window_with_metrics(RadarParams.SP.RDM.window_type_doppler, num_chirps_doppler, 60);
RadarParams.SP.CFAR.method = 'OS'; % 'CA' 또는 'OS'
RadarParams.SP.CFAR.dimension = '2D'; % '1D' 또는 '2D'
RadarParams.SP.CFAR.axis = 'doppler'; % 1D일 때만 사용: 'range' 또는 'doppler'
RadarParams.SP.CFAR.pfa = 1e-6; % false alarm 확률
RadarParams.SP.CFAR.train = [8, 8]; % [doppler, range] training cell 수 (1D면 첫 값 사용)
RadarParams.SP.CFAR.guard = [2, 2]; % [doppler, range] guard cell 수 (1D면 첫 값 사용)
RadarParams.SP.CFAR.rank = 0.75; % OS-CFAR rank 비율(0~1)
RadarParams.SP.CFAR.os_scale = 15.0; % OS-CFAR 임계 스케일
% 8) Secondary surface loss (안테나 반사 손실)
RadarParams.Antenna.SecondarySurfaceLoss_dB = 3;
% 9) 커버리지 분석 파라미터
RadarParams.Coverage.R_max = 10; % 최대 탐지 거리 (m)
RadarParams.Coverage.RCS_dBsm = 0; % 표적 RCS (dBsm)
%% 2. 모듈별 함수 호출 (TX 파이프라인)
% step 0. 파형 시각화를 위한 시간 벡터 및 TX 마스크 생성
Target = RadarParams.Target;
TxPattern = RadarParams.Antenna.TxPattern;
RxPattern = RadarParams.Antenna.RxPattern;
NumTx = RadarParams.Antenna.NumTx;
NumChirps = RadarParams.Waveform.NumChirps;
T_chirp = RadarParams.Waveform.Timing.IdleTime + RadarParams.Waveform.Timing.RampEndTime;
T_frame = T_chirp * NumChirps;
[t, tx_mask] = generate_waveform_timing(RadarParams);
% ================= ADC Raw Data 생성 파트 (step 1 ~ 6) =================
% step 1. 송신 안테나 이득 산출 (Ptx 반영 안함)
TxOut = radiate_antenna(Target, TxPattern);
% step 2. 채널 전파 (TTD 및 공간 감쇠 산출)
ChannelOut = apply_channel_effects(RadarParams);
% step 3. 수신 안테나 이득 결합
RxOut = receive_antenna(ChannelOut, Target, RxPattern);
% step 4-1. 물리적 이득 통합 (TX_Gain * Space_Loss * RX_Gain)
% 아직 RF 파워(V_tx)가 곱해지지 않은 상태의 "시스템 전달 함수" 진폭입니다.
SystemAmp = zeros(size(RxOut.space_loss_amp));
for k = 1:Target.NumTargets
for tx = 1:NumTx
SystemAmp(k, :, tx, :, :) = RxOut.space_loss_amp(k, :, tx, :, :) * TxOut.G_tx_amp(k, tx);
end
end
% step 4-2. 수신 RF/IF 체인 모델링 및 ADC 입력 신호 생성
% - 기능: 경로 감쇠/위상, PA 출력, 수신 이득, 잡음, MIMO 모드, non-ideal, spur를 반영해
% RX 채널별 디지털화 직전 신호를 생성합니다.
% - 출력 1) adc_raw_data : [NumRx x NumTx x NumChirps x N_adc_samples]
% TX별로 분리된 분석용 원시 신호(각 TX 성분이 분리되어 저장됨)
% - 출력 2) adc_combined : [NumRx x NumChirps x N_adc_samples]
% 실제 ADC 입력을 모사한 합산 신호(각 RX에서 모든 TX 성분이 합쳐진 신호)
[adc_raw_data, adc_combined] = apply_lna_and_mixer(RxOut, TxOut, RadarParams);
% step 5. ADC Combined 신호 (실제 ADC 입력) 생성 및 HPF 적용
adc_combined_hpf = apply_analog_hpf(adc_combined, RadarParams.Waveform.fs_adc, RadarParams.Rxpath.fc_hpf);
% step 6. ADC 모델링 (Quantization & Clipping)
% 하드웨어 사양 파라미터는 서두에서 정의됨
v_peak = max(abs(adc_combined_hpf(:)));
lsb_val = RadarParams.Rxpath.adc_v_full_scale / (2^RadarParams.Rxpath.adc_bits);
% ADC 양자화
adc_digital = apply_adc_quantization(adc_combined_hpf, RadarParams.Rxpath.adc_bits, RadarParams.Rxpath.adc_v_full_scale, RadarParams.Rxpath.receiver_mode);
% ================= 신호처리 파트 (step 7 ~ ) =================
% step 7. Range-FFT 및 Ideal LPF 적용
% LPF 차단 주파수와 윈도우 타입은 앞쪽에서 정의됨
% (RadarParams.Rxpath.fc_lpf, RadarParams.SP.RDM.*)
% adc_digital을 [NumRx, 1, NumChirps, N_samples] 형태로 변환 (process_range_fft_lpf 호환성)
adc_digital_expanded = reshape(adc_digital, [size(adc_digital,1), 1, size(adc_digital,2), size(adc_digital,3)]);
[range_data, r_axis] = process_range_fft_lpf(adc_digital_expanded, RadarParams);
% step 8. Range Profile 시각화 (1번 채널, 1번 처프)
if PlotToggle.range_profile
figure('Name', 'Range Profile with Ideal LPF');
plot(r_axis, 20*log10(abs(squeeze(range_data(1,1,1,:)))));
grid on; hold on;
xlabel('Range (m)');
ylabel('Magnitude (dB)');
title(['Range Profile (LPF Cut-off: ', num2str(RadarParams.Rxpath.fc_lpf/1e6), ' MHz)']);
% LPF 컷오프 지점 표시
xline((RadarParams.Rxpath.fc_lpf * RadarParams.Basic.c)/(2*RadarParams.Waveform.Slope), '--r', 'LPF Cut-off');
end
% step 9. Doppler-FFT 수행
[rd_cube, v_axis] = process_doppler_fft(range_data, RadarParams);
% step 10. NumRx 비코히어런트 적분(Noncoherent Integration) RDM 생성
target_rd_map = integrate_nci_rdm(rd_cube, RadarParams); % [Doppler x Range]
% step 11. CFAR 기반 표적 탐지 (OS/CA, 1D/2D, range/doppler 선택 가능)
[cfar_mask, cfar_threshold, cfar_detections] = detect_targets_cfar(target_rd_map, RadarParams);
%% 3. 결과 시각화 (Single Chirp & Multi-Chirp)
% [Figure 1] 단일 처프 정밀 타이밍 분석
T_chirp = RadarParams.Waveform.Timing.IdleTime + RadarParams.Waveform.Timing.RampEndTime;
idx_single = (t <= T_chirp);
t_single = t(idx_single);
tx_mask_single = tx_mask(idx_single);
fig_single = [];
if PlotToggle.tx_single
fig_single = visualize_tx_waveform(t_single, RadarParams.Waveform.Timing, RadarParams.Waveform.fc, RadarParams.Waveform.f_start, RadarParams.Waveform.Slope, tx_mask_single, RadarParams.Waveform.nonideal.peak_phase_error, RadarParams.Waveform.nonideal.f_ripple);
end
% [Figure 2] 다중 처프 프레임 시퀀스 및 MIMO 변조 확인
% (수정됨: mimoMode와 NumTx 변수를 추가로 전달)
fig_multi = [];
if PlotToggle.tx_multi
fig_multi = visualize_multi_tx_waveform(t, RadarParams.Waveform.Timing, RadarParams.Waveform.fc, RadarParams.Waveform.f_start, RadarParams.Waveform.Slope, tx_mask, NumChirps, RadarParams.Waveform.mimoMode, NumTx);
end
% --- [ Figure 3, 4: 안테나 방사 패턴 단면 도시 ] ---
% 'TX'와 'RX'라는 이름을 넘겨주어 그래프 타이틀과 범례를 구분합니다.
fig_tx_ant = [];
if PlotToggle.tx_antenna
fig_tx_ant = visualize_antenna_pattern(TxPattern, 'TX');
end
fig_rx_ant = [];
if PlotToggle.rx_antenna
fig_rx_ant = visualize_antenna_pattern(RxPattern, 'RX');
end
% [Figure 5] Range-Doppler Map 시각화 (NumRx NCI RDM)
fig_rd_map = [];
if PlotToggle.rd_map
fig_rd_map = visualize_rd_map_with_spurs(target_rd_map, r_axis, v_axis, Target, RadarParams.SpurParams, RadarParams, RadarParams.Waveform.Slope);
end
% [Figure 6] CFAR 탐지 결과 시각화 (2D MAP 위 원 마커)
fig_cfar = [];
if PlotToggle.cfar
fig_cfar = figure('Name', 'CFAR Detections on NCI RDM');
imagesc(r_axis, v_axis, 20*log10(abs(target_rd_map)));
axis xy;
colormap(jet);
colorbar;
xlabel('Range (m)');
ylabel('Velocity (m/s)');
title('CFAR Detections (Circle Markers)');
hold on;
if ~isempty(cfar_detections)
det_d_idx = cfar_detections(:,1); % Doppler bin index
det_r_idx = cfar_detections(:,2); % Range bin index
det_r = r_axis(det_r_idx);
det_v = v_axis(det_d_idx);
plot(det_r, det_v, 'wo', 'MarkerSize', 7, 'LineWidth', 1.5);
end
hold off;
end
% ================= Coverage Analysis (Performance Analysis) =================
% [Figure 7] Angular Coverage 분석: 2D 안테나 패턴 기반 효율적 SNR 계산
% 거리 100m, RCS 0 dBsm 표적의 각도별 SNR 분석
snr_coverage_2d = [];
azimuth_deg = [];
elevation_deg = [];
coverage_info = [];
fig_coverage = [];
if PlotToggle.coverage
[snr_coverage_2d, azimuth_deg, elevation_deg, coverage_info, fig_coverage] = analyze_coverage(RadarParams, RadarParams.Coverage.R_max, RadarParams.Coverage.RCS_dBsm);
end