From a70aa68053f249e457359422e672612f86d62bfc Mon Sep 17 00:00:00 2001 From: YKG Date: Wed, 4 Mar 2026 22:05:26 +0900 Subject: [PATCH] =?UTF-8?q?RDM=20dBm/bin=20=EB=8B=A8=EC=9C=84=20PSD=20?= =?UTF-8?q?=EB=8F=84=EC=8B=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../visualize_rd_map_with_spurs.m | 27 +++++++++++-- Main.m | 39 ++++++++++++++++--- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/04. Signal Processing/visualize_rd_map_with_spurs.m b/04. Signal Processing/visualize_rd_map_with_spurs.m index 982608f..f536223 100644 --- a/04. Signal Processing/visualize_rd_map_with_spurs.m +++ b/04. Signal Processing/visualize_rd_map_with_spurs.m @@ -13,13 +13,34 @@ function fig = visualize_rd_map_with_spurs(target_rd_map, r_axis, v_axis, Target % 출력: % - fig: 생성된 figure 핸들 + if ~isfield(RadarParams, 'SP') || ~isfield(RadarParams.SP, 'RDM') || ... + ~isfield(RadarParams.SP.RDM, 'window_range') || ~isfield(RadarParams.SP.RDM, 'window_doppler') + error('RadarParams.SP.RDM.window_range / window_doppler 정보가 필요합니다.'); + end + + win_r = RadarParams.SP.RDM.window_range; + win_d = RadarParams.SP.RDM.window_doppler; + + normal_factor = RadarParams.Rxpath.fc_lpf * RadarParams.Waveform.PRF * sum(win_r.^2) * sum(win_d.^2); + + if ~isfield(RadarParams, 'Rxpath') || ~isfield(RadarParams.Rxpath, 'load_impedance_ohm') + error('RadarParams.Rxpath.load_impedance_ohm 값이 필요합니다.'); + end + load_impedance_ohm = RadarParams.Rxpath.load_impedance_ohm; + + psd2d_w_hz2 = (abs(target_rd_map).^2) / (load_impedance_ohm * max(normal_factor, eps)); + rbw_range_hz = RadarParams.Waveform.fs_adc * sum(win_r.^2) / max(eps, (sum(win_r)^2)); + rbw_doppler_hz = RadarParams.Waveform.PRF * sum(win_d.^2) / max(eps, (sum(win_d)^2)); + rd_map_dbm_bin = 10*log10(max(psd2d_w_hz2, realmin) / 1e-3) + 10*log10(max(rbw_range_hz * rbw_doppler_hz, eps)); + fig = figure('Name', '2D Range-Doppler Map'); - imagesc(r_axis, v_axis, 20*log10(abs(target_rd_map))); + imagesc(r_axis, v_axis, rd_map_dbm_bin); axis xy; % y축 방향(속도)을 위로 정렬 - colorbar; + cb = colorbar; + cb.Label.String = 'Power (dBm/bin)'; xlabel('Range (m)'); ylabel('Velocity (m/s)'); - title('Range-Doppler Map (Single Channel)'); + title('Range-Doppler Map (dBm/bin)'); colormap(jet); % 범례용 핸들 및 레이블 수집 diff --git a/Main.m b/Main.m index 5e269f3..4c21b9c 100644 --- a/Main.m +++ b/Main.m @@ -70,11 +70,11 @@ RadarParams.Antenna.TxPattern = build_antenna_patterns(RadarParams.Antenna.NumTx RadarParams.Antenna.RxPattern = build_antenna_patterns(RadarParams.Antenna.NumRx, '2D', 14, 2, 40, 15, RadarParams.Antenna.rx_files); % 5) 타겟 모델링 -RadarParams.Target.R = [12, 80, 120]; % 타겟 거리 (m) -RadarParams.Target.v = [7, -5, 0]; % 타겟 속도 (m/s) -RadarParams.Target.rcs = [10, 5, 20]; % 타겟 RCS (dBsm) -RadarParams.Target.az = [10, -10, 0]; % 방위각 (deg) -RadarParams.Target.el = [0, 0, 5]; % 고각 (deg) +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) 수신단 파라미터 @@ -83,6 +83,7 @@ RadarParams.Rxpath.fc_lpf = 0.8*RadarParams.Waveform.fs_adc/2; % L 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) @@ -103,6 +104,34 @@ RadarParams.SpurParams.enabled = false; % spur on/of % 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; + +if strcmpi(RadarParams.SP.RDM.window_type_range, 'none') + RadarParams.SP.RDM.window_range = ones(1, num_samples_range); +elseif strcmpi(RadarParams.SP.RDM.window_type_range, 'hamming') + RadarParams.SP.RDM.window_range = hamming(num_samples_range)'; +elseif strcmpi(RadarParams.SP.RDM.window_type_range, 'blackman') + RadarParams.SP.RDM.window_range = blackman(num_samples_range)'; +elseif strcmpi(RadarParams.SP.RDM.window_type_range, 'chebwin') + RadarParams.SP.RDM.window_range = chebwin(num_samples_range, 60)'; +else + RadarParams.SP.RDM.window_range = hann(num_samples_range)'; +end + +if strcmpi(RadarParams.SP.RDM.window_type_doppler, 'none') + RadarParams.SP.RDM.window_doppler = ones(1, num_chirps_doppler); +elseif strcmpi(RadarParams.SP.RDM.window_type_doppler, 'hamming') + RadarParams.SP.RDM.window_doppler = hamming(num_chirps_doppler)'; +elseif strcmpi(RadarParams.SP.RDM.window_type_doppler, 'blackman') + RadarParams.SP.RDM.window_doppler = blackman(num_chirps_doppler)'; +elseif strcmpi(RadarParams.SP.RDM.window_type_doppler, 'hann') + RadarParams.SP.RDM.window_doppler = hann(num_chirps_doppler)'; +else + RadarParams.SP.RDM.window_doppler = chebwin(num_chirps_doppler, 60)'; +end + RadarParams.SP.CFAR.method = 'OS'; % 'CA' 또는 'OS' RadarParams.SP.CFAR.dimension = '2D'; % '1D' 또는 '2D' RadarParams.SP.CFAR.axis = 'doppler'; % 1D일 때만 사용: 'range' 또는 'doppler'