1. SNR 신호처리, Secondary surface 영향 고려하여 SNR 재계산
2. Coverage Figure 개선 3. 윈도우 생성 및 성능 계산 함수 추가
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
function [windowVector, metrics] = create_window_with_metrics(windowType, windowLength, varargin)
|
||||
% CREATE_WINDOW_WITH_METRICS - 윈도우 함수 생성 및 성능 지표 계산
|
||||
%
|
||||
% 입력:
|
||||
% windowType - 윈도우 타입 문자열: 'none', 'hann', 'hamming', 'blackman', 'chebwin'
|
||||
% windowLength - 윈도우 길이 (샘플 수)
|
||||
% varargin - 추가 파라미터 (예: chebwin의 경우 sidelobe level)
|
||||
%
|
||||
% 출력:
|
||||
% windowVector - 생성된 윈도우 벡터 (1 x windowLength)
|
||||
% metrics - 윈도우 성능 지표 구조체
|
||||
% .type : 윈도우 타입
|
||||
% .length : 윈도우 길이
|
||||
% .snr_loss_dB : SNR 손실 (dB)
|
||||
% .scalloping_loss_dB: Scalloping 손실 (dB)
|
||||
% .coherent_gain : 코히어런트 이득
|
||||
% .enbw : Equivalent Noise Bandwidth (bins)
|
||||
|
||||
% 기본 파라미터 설정
|
||||
if windowLength <= 0
|
||||
error('Window length must be positive.');
|
||||
end
|
||||
|
||||
% 윈도우 함수 생성
|
||||
switch lower(windowType)
|
||||
case 'none'
|
||||
windowVector = ones(1, windowLength);
|
||||
|
||||
case 'hann'
|
||||
windowVector = hann(windowLength)';
|
||||
|
||||
case 'hamming'
|
||||
windowVector = hamming(windowLength)';
|
||||
|
||||
case 'blackman'
|
||||
windowVector = blackman(windowLength)';
|
||||
|
||||
case 'chebwin'
|
||||
% Chebyshev 윈도우는 sidelobe level 파라미터 필요 (기본값: 60dB)
|
||||
if ~isempty(varargin)
|
||||
sidelobe_dB = varargin{1};
|
||||
else
|
||||
sidelobe_dB = 60;
|
||||
end
|
||||
windowVector = chebwin(windowLength, sidelobe_dB)';
|
||||
|
||||
otherwise
|
||||
warning('Unknown window type "%s". Using Hann window as default.', windowType);
|
||||
windowVector = hann(windowLength)';
|
||||
windowType = 'hann';
|
||||
end
|
||||
|
||||
% 윈도우 성능 지표 계산
|
||||
metrics = calculate_window_metrics(windowVector, windowType);
|
||||
end
|
||||
|
||||
|
||||
function metrics = calculate_window_metrics(windowVector, windowType)
|
||||
% CALCULATE_WINDOW_METRICS - 윈도우 함수의 성능 지표 계산
|
||||
%
|
||||
% 계산 항목:
|
||||
% 1. SNR Loss (dB) : 윈도우 적용으로 인한 SNR 손실
|
||||
% 2. Scalloping Loss (dB): FFT bin 사이(0.5 bin offset)에서의 최대 손실
|
||||
% 3. Coherent Gain : 윈도우의 평균 진폭
|
||||
% 4. ENBW (bins) : Equivalent Noise Bandwidth
|
||||
|
||||
w = windowVector(:).'; % Row vector로 변환
|
||||
N = numel(w);
|
||||
|
||||
if N == 0
|
||||
metrics = struct('type', windowType, 'length', 0, ...
|
||||
'snr_loss_dB', NaN, 'scalloping_loss_dB', NaN, ...
|
||||
'coherent_gain', NaN, 'enbw', NaN);
|
||||
return;
|
||||
end
|
||||
|
||||
% 1. Coherent Gain (코히어런트 이득)
|
||||
coherent_gain = mean(w);
|
||||
|
||||
% 2. Noise Power Gain (잡음 전력 이득)
|
||||
noise_power_gain = mean(abs(w).^2);
|
||||
|
||||
% 3. SNR Loss (dB)
|
||||
% SNR_loss = (Noise Power Gain) / (Coherent Gain)^2
|
||||
% 이는 윈도우 적용 시 신호 대 잡음비가 얼마나 감소하는지를 나타냄
|
||||
if abs(coherent_gain) > eps
|
||||
snr_loss_linear = noise_power_gain / (abs(coherent_gain)^2);
|
||||
snr_loss_dB = 10 * log10(snr_loss_linear);
|
||||
else
|
||||
snr_loss_dB = NaN;
|
||||
end
|
||||
|
||||
% 4. Equivalent Noise Bandwidth (ENBW)
|
||||
% ENBW는 윈도우가 얼마나 많은 주파수 bin의 잡음을 통과시키는지 나타냄
|
||||
enbw = N * noise_power_gain / (sum(w)^2);
|
||||
|
||||
% 5. Scalloping Loss (dB)
|
||||
% FFT bin 중간(0.5 bin offset)에 신호가 위치할 때의 최대 손실
|
||||
% 이는 가장 나쁜 경우의 신호 손실을 나타냄
|
||||
sample_index = 0:(N-1);
|
||||
half_bin_response = abs(sum(w .* exp(-1j * 2 * pi * 0.5 * sample_index / N)));
|
||||
dc_response = abs(sum(w));
|
||||
|
||||
if dc_response > eps
|
||||
scalloping_loss_dB = -20 * log10(half_bin_response / dc_response);
|
||||
else
|
||||
scalloping_loss_dB = NaN;
|
||||
end
|
||||
|
||||
% 결과 구조체 생성
|
||||
metrics = struct(...
|
||||
'type', lower(windowType), ...
|
||||
'length', N, ...
|
||||
'snr_loss_dB', snr_loss_dB, ...
|
||||
'scalloping_loss_dB', scalloping_loss_dB, ...
|
||||
'coherent_gain', coherent_gain, ...
|
||||
'enbw', enbw);
|
||||
end
|
||||
@@ -3,7 +3,6 @@ function [rd_map, doppler_axis] = process_doppler_fft(range_profile, RadarParams
|
||||
% - range_profile: [NumRx, NumTx, NumChirps, NumRangeBins]
|
||||
% - RadarParams: 메인 파라미터 구조체
|
||||
NumChirps = RadarParams.Waveform.NumChirps;
|
||||
window_type = RadarParams.SP.RDM.window_type_doppler;
|
||||
|
||||
[~, ~, ~, ~] = size(range_profile);
|
||||
% 중심 주파수에서의 파장
|
||||
@@ -12,18 +11,10 @@ function [rd_map, doppler_axis] = process_doppler_fft(range_profile, RadarParams
|
||||
% 1. 처프 간 반복 주기 (PRI, Pulse Repetition Interval)
|
||||
T_pri = RadarParams.Waveform.PRI;
|
||||
|
||||
% 2. Doppler-FFT용 윈도우 함수 (사용자 선택 가능)
|
||||
% 도플러 방향(3번째 차원)으로 사이드로브를 억제합니다.
|
||||
if strcmpi(window_type, 'none')
|
||||
win_doppler = ones(1, NumChirps);
|
||||
elseif strcmpi(window_type, 'hamming')
|
||||
win_doppler = hamming(NumChirps)';
|
||||
elseif strcmpi(window_type, 'blackman')
|
||||
win_doppler = blackman(NumChirps)';
|
||||
elseif strcmpi(window_type, 'hann')
|
||||
win_doppler = hann(NumChirps)';
|
||||
else % default: 'chebwin'
|
||||
win_doppler = chebwin(NumChirps, 60)'; % 60dB 사이드로브 억제
|
||||
% 2. Main.m에서 생성된 Doppler-FFT용 윈도우 함수 적용
|
||||
win_doppler = RadarParams.SP.RDM.window_doppler;
|
||||
if length(win_doppler) ~= NumChirps
|
||||
error('Doppler window length mismatch: expected %d, got %d', NumChirps, length(win_doppler));
|
||||
end
|
||||
win_data = range_profile .* reshape(win_doppler, [1, 1, NumChirps, 1]);
|
||||
|
||||
|
||||
@@ -5,22 +5,14 @@ function [range_profile, range_axis] = process_range_fft_lpf(adc_raw_data, Radar
|
||||
fs_adc = RadarParams.Waveform.fs_adc;
|
||||
Slope = RadarParams.Waveform.Slope;
|
||||
fc_lpf_Hz = RadarParams.Rxpath.fc_lpf;
|
||||
window_type = RadarParams.SP.RDM.window_type_range;
|
||||
|
||||
[~, ~, ~, N_samples] = size(adc_raw_data);
|
||||
c = RadarParams.Basic.c;
|
||||
|
||||
% 1. 윈도우 함수 적용
|
||||
if strcmpi(window_type, 'none')
|
||||
win = ones(1, N_samples);
|
||||
elseif strcmpi(window_type, 'hamming')
|
||||
win = hamming(N_samples)';
|
||||
elseif strcmpi(window_type, 'blackman')
|
||||
win = blackman(N_samples)';
|
||||
elseif strcmpi(window_type, 'chebwin')
|
||||
win = chebwin(N_samples, 60)';
|
||||
else % default: 'hann'
|
||||
win = hann(N_samples)';
|
||||
% 1. Main.m에서 생성된 윈도우 함수 적용
|
||||
win = RadarParams.SP.RDM.window_range;
|
||||
if length(win) ~= N_samples
|
||||
error('Window length mismatch: expected %d, got %d', N_samples, length(win));
|
||||
end
|
||||
win_data = adc_raw_data .* reshape(win, [1, 1, 1, N_samples]);
|
||||
|
||||
|
||||
@@ -150,9 +150,29 @@ function [snr_coverage_2d, azimuth_deg, elevation_deg, coverage_info, fig] = ana
|
||||
% 이득을 선형으로 변환
|
||||
g_tx_linear_grid = 10.^(g_tx_db_grid / 10);
|
||||
g_rx_linear_grid = 10.^(g_rx_db_grid / 10);
|
||||
|
||||
% 신호처리 이득
|
||||
SP_gain_rngFFT = RadarParams.Waveform.Timing.AdcSampTime * RadarParams.Waveform.fs_adc;
|
||||
SP_gain_dopFFT = RadarParams.Waveform.NumChirps;
|
||||
SP_loss_rngwin = 10^(RadarParams.SP.RDM.window_metrics_range.snr_loss_dB / 10);
|
||||
SP_loss_dopwin = 10^(RadarParams.SP.RDM.window_metrics_doppler.snr_loss_dB / 10);
|
||||
SP_loss_rng_straddle = 10^(RadarParams.SP.RDM.window_metrics_range.scalloping_loss_dB / 10);
|
||||
SP_loss_dop_straddle = 10^(RadarParams.SP.RDM.window_metrics_doppler.scalloping_loss_dB / 10);
|
||||
SP_total = SP_gain_rngFFT * SP_gain_dopFFT / (SP_loss_rngwin * SP_loss_dopwin * SP_loss_rng_straddle * SP_loss_dop_straddle);
|
||||
|
||||
% Secondary Surface Loss
|
||||
secondary_loss = 10^(RadarParams.Antenna.SecondarySurfaceLoss_dB / 10);
|
||||
|
||||
fprintf('SP gain rng FFT: %.2f, SP gain doppler FFT: %.2f\n', SP_gain_rngFFT, SP_gain_dopFFT);
|
||||
fprintf('SP loss range window: %.2f dB, SP loss doppler window: %.2f dB\n', RadarParams.SP.RDM.window_metrics_range.snr_loss_dB, RadarParams.SP.RDM.window_metrics_doppler.snr_loss_dB);
|
||||
fprintf('SP loss range straddle: %.2f dB, SP loss doppler straddle: %.2f dB\n', RadarParams.SP.RDM.window_metrics_range.scalloping_loss_dB, RadarParams.SP.RDM.window_metrics_doppler.scalloping_loss_dB);
|
||||
fprintf('SP loss doppler window: %.2f dB\n', RadarParams.SP.RDM.window_metrics_doppler.snr_loss_dB);
|
||||
fprintf('SP loss doppler straddle: %.2f dB\n', RadarParams.SP.RDM.window_metrics_doppler.scalloping_loss_dB);
|
||||
fprintf('Secondary surface loss: %.2f dB\n', RadarParams.Antenna.SecondarySurfaceLoss_dB);
|
||||
|
||||
% SNR 계산: 벡터화 연산 (스칼라 항 × 2D 배열)
|
||||
p_rx_w = (ptx_w * g_tx_linear_grid .* g_rx_linear_grid * (lambda^2) * rcs_target) / ((path_loss_factor^2) * (4 * pi));
|
||||
p_rx_w = (ptx_w * (lambda^2) * rcs_target) / ((path_loss_factor^2) * (4 * pi)) * SP_total / secondary_loss;
|
||||
p_rx_w = p_rx_w * g_tx_linear_grid .* g_rx_linear_grid; % 연산량 최적화를 위해 안테나 이득을 나중에 곱함
|
||||
p_rx_after_rxgain_w = p_rx_w * rxGain_linear;
|
||||
snr_linear = p_rx_after_rxgain_w / total_noise_power_w;
|
||||
snr_coverage_2d = 10 * log10(max(snr_linear, eps));
|
||||
@@ -194,38 +214,18 @@ function [snr_coverage_2d, azimuth_deg, elevation_deg, coverage_info, fig] = ana
|
||||
coverage_info.max_snr_y_m = y_grid_m(max_el_idx_2d, max_az_idx_2d);
|
||||
coverage_info.max_snr_z_m = z_grid_m(max_el_idx_2d, max_az_idx_2d);
|
||||
|
||||
%% 3D + 1D Cut 시각화
|
||||
fig = figure('Name', 'Coverage Analysis - 3D + 1D Cut');
|
||||
%% 3D Coverage 시각화
|
||||
fig = figure('Name', 'Coverage Analysis - 3D');
|
||||
set(fig, 'Position', [100, 100, 1600, 900]);
|
||||
|
||||
% 1D cut SNR 추출
|
||||
[~, el_idx_zero] = min(abs(elevation_deg - 0));
|
||||
[~, az_idx_zero] = min(abs(azimuth_deg - 0));
|
||||
snr_az_cut = snr_coverage_2d(el_idx_zero, :); % elevation=0 cut
|
||||
snr_el_cut = snr_coverage_2d(:, az_idx_zero); % azimuth=0 cut
|
||||
|
||||
% Subplot 1: x-SNR Cut (elevation=0)
|
||||
subplot(2, 3, 1);
|
||||
x_cut_m = target_range_m .* cosd(azimuth_deg);
|
||||
plot(x_cut_m, snr_az_cut, 'b-', 'LineWidth', 2);
|
||||
hold on;
|
||||
[~, max_idx_az] = max(snr_az_cut);
|
||||
plot(x_cut_m(max_idx_az), snr_az_cut(max_idx_az), 'r*', 'MarkerSize', 15, 'LineWidth', 2);
|
||||
grid on;
|
||||
xlabel('x (m)');
|
||||
ylabel('SNR (dB)');
|
||||
title('1D CUT: elevation = 0 deg');
|
||||
hold off;
|
||||
|
||||
% Subplot 2: z-SNR Cut (azimuth=0)
|
||||
subplot(2, 3, 2);
|
||||
z_cut_m = target_range_m .* sind(elevation_deg);
|
||||
plot(z_cut_m, snr_el_cut, 'g-', 'LineWidth', 2);
|
||||
hold on;
|
||||
[~, max_idx_el] = max(snr_el_cut);
|
||||
plot(z_cut_m(max_idx_el), snr_el_cut(max_idx_el), 'r*', 'MarkerSize', 15, 'LineWidth', 2);
|
||||
grid on;
|
||||
xlabel('z (m)');
|
||||
ylabel('SNR (dB)');
|
||||
title('1D CUT: azimuth = 0 deg');
|
||||
hold off;
|
||||
|
||||
% Subplot 3: x-y top view (color = SNR at elevation=0)
|
||||
subplot(2, 3, 3);
|
||||
% Subplot 1: x-y top view (color = SNR at elevation=0 cut)
|
||||
ax_topview = subplot(2, 2, 3);
|
||||
x_top_m = target_range_m .* cosd(azimuth_deg);
|
||||
y_top_m = target_range_m .* sind(azimuth_deg);
|
||||
scatter(x_top_m, y_top_m, 45, snr_az_cut, 'filled');
|
||||
@@ -235,10 +235,10 @@ function [snr_coverage_2d, azimuth_deg, elevation_deg, coverage_info, fig] = ana
|
||||
ylabel(cb, 'SNR (dB)');
|
||||
xlabel('x (m)');
|
||||
ylabel('y (m)');
|
||||
title('Top View (elevation = 0 deg)');
|
||||
title('Top View (Azimuth)');
|
||||
|
||||
% Subplot 4-5: 3D Surface (geometry = x,y,z, color = SNR)
|
||||
subplot(2, 3, 4:5, 'replace');
|
||||
% Subplot 2: 3D Surface (geometry = x,y,z, color = SNR) - spans full width at top
|
||||
ax_3d = subplot(2, 2, 1:2);
|
||||
surf(x_grid_m, y_grid_m, z_grid_m, snr_coverage_2d, 'EdgeColor', 'none');
|
||||
colormap(jet);
|
||||
cb_3d = colorbar;
|
||||
@@ -246,48 +246,15 @@ function [snr_coverage_2d, azimuth_deg, elevation_deg, coverage_info, fig] = ana
|
||||
xlabel('x (m)');
|
||||
ylabel('y (m)');
|
||||
zlabel('z (m)');
|
||||
title('3D Coverage in Cartesian Coordinates (Click to inspect)');
|
||||
title('3D Coverage in Cartesian Coordinates');
|
||||
view(45, 30);
|
||||
grid on;
|
||||
hold on;
|
||||
plot3(coverage_info.max_snr_x_m, coverage_info.max_snr_y_m, coverage_info.max_snr_z_m, 'r*', 'MarkerSize', 20, 'LineWidth', 2);
|
||||
hold off;
|
||||
|
||||
% Datacursor mode 활성화 (클릭 기능)
|
||||
dcm_obj = datacursormode(fig);
|
||||
dcm_obj.Enable = 'on';
|
||||
set(dcm_obj, 'UpdateFcn', @datatip_update_callback);
|
||||
set(dcm_obj, 'SnapToDataVertex', 'on');
|
||||
|
||||
% Help text
|
||||
fprintf('\n>>> Data Cursor Mode ENABLED <<<\n');
|
||||
fprintf('Instructions:\n');
|
||||
fprintf(' 1. Left-click on the 3D surface to inspect points\n');
|
||||
fprintf(' 2. Tooltip shows x, y, z (m) and SNR[dB]\n');
|
||||
fprintf(' 3. Press Escape or click "Disable Data Cursor" in Figure Tools to deactivate\n\n');
|
||||
|
||||
%% Nested function for datacursor callback
|
||||
function output_txt = datatip_update_callback(~, event)
|
||||
pos = event.Position;
|
||||
x_val = pos(1);
|
||||
y_val = pos(2);
|
||||
z_val = pos(3);
|
||||
|
||||
dist2 = (x_grid_m - x_val).^2 + (y_grid_m - y_val).^2 + (z_grid_m - z_val).^2;
|
||||
[~, nearest_idx] = min(dist2(:));
|
||||
[nearest_el_idx, nearest_az_idx] = ind2sub(size(dist2), nearest_idx);
|
||||
snr_val = snr_coverage_2d(nearest_el_idx, nearest_az_idx);
|
||||
|
||||
output_txt = {
|
||||
['x: ' num2str(x_val, '%.3f') ' m']
|
||||
['y: ' num2str(y_val, '%.3f') ' m']
|
||||
['z: ' num2str(z_val, '%.3f') ' m']
|
||||
['SNR[dB]: ' num2str(snr_val, '%.3f')]
|
||||
};
|
||||
end
|
||||
|
||||
% Subplot 6: x-z side view (azimuth=0, color=SNR)
|
||||
subplot(2, 3, 6);
|
||||
% Subplot 3: x-z side view (azimuth=0, color=SNR at azimuth=0 cut)
|
||||
ax_sideview = subplot(2, 2, 4);
|
||||
x_side_m = target_range_m .* cosd(elevation_deg);
|
||||
z_side_m = target_range_m .* sind(elevation_deg);
|
||||
scatter(x_side_m, z_side_m, 45, snr_el_cut, 'filled');
|
||||
@@ -296,12 +263,31 @@ function [snr_coverage_2d, azimuth_deg, elevation_deg, coverage_info, fig] = ana
|
||||
ylabel(cb_side, 'SNR (dB)');
|
||||
xlabel('x (m)');
|
||||
ylabel('z (m)');
|
||||
title('Side View (azimuth = 0 deg)');
|
||||
title('Side View (Elevation)');
|
||||
|
||||
% 전체 타이틀
|
||||
sgtitle(sprintf('3D Coverage (x,y,z) | Max SNR: %.2f dB at (%.2f, %.2f, %.2f) m', ...
|
||||
coverage_info.max_snr, coverage_info.max_snr_x_m, coverage_info.max_snr_y_m, coverage_info.max_snr_z_m), 'FontSize', 12);
|
||||
|
||||
% 단일 Data Cursor Mode 설정 (모든 축에 적용)
|
||||
dcm_obj = datacursormode(fig);
|
||||
dcm_obj.Enable = 'on';
|
||||
set(dcm_obj, 'UpdateFcn', {@unified_datatip_callback, ...
|
||||
ax_topview, ax_3d, ax_sideview, ...
|
||||
x_top_m, y_top_m, snr_az_cut, azimuth_deg, ...
|
||||
x_grid_m, y_grid_m, z_grid_m, snr_coverage_2d, elevation_deg, ...
|
||||
x_side_m, z_side_m, snr_el_cut});
|
||||
dcm_obj.SnapToDataVertex = 'on';
|
||||
|
||||
% Help text
|
||||
fprintf('\n>>> Data Cursor Mode ENABLED <<<\n');
|
||||
fprintf('Instructions:\n');
|
||||
fprintf(' 1. Left-click on any plot to inspect points\n');
|
||||
fprintf(' 2. Top View shows: x, y, Azimuth, SNR\n');
|
||||
fprintf(' 3. 3D Surface shows: x, y, z, Azimuth, Elevation, SNR\n');
|
||||
fprintf(' 4. Side View shows: x, z, Elevation, SNR\n');
|
||||
fprintf(' 5. Press Escape or click "Disable Data Cursor" in Figure Tools to deactivate\n\n');
|
||||
|
||||
%% 통계 출력
|
||||
fprintf('\n===== 3D COVERAGE ANALYSIS REPORT (Cartesian x,y,z) =====\n');
|
||||
fprintf('Target Configuration:\n');
|
||||
@@ -313,12 +299,81 @@ function [snr_coverage_2d, azimuth_deg, elevation_deg, coverage_info, fig] = ana
|
||||
fprintf(' - Max SNR: %.2f dB @ (x,y,z)=(%.2f, %.2f, %.2f) m\n', coverage_info.max_snr, coverage_info.max_snr_x_m, coverage_info.max_snr_y_m, coverage_info.max_snr_z_m);
|
||||
fprintf(' - Min SNR: %.2f dB\n', coverage_info.min_snr);
|
||||
fprintf(' - SNR Range: %.2f dB\n', coverage_info.max_snr - coverage_info.min_snr);
|
||||
fprintf('\n1D CUT Statistics:\n');
|
||||
fprintf(' - elevation=0 cut: Max=%.2f dB, Min=%.2f dB\n', max(snr_az_cut), min(snr_az_cut));
|
||||
fprintf(' - azimuth=0 cut: Max=%.2f dB, Min=%.2f dB\n', max(snr_el_cut), min(snr_el_cut));
|
||||
fprintf('System Parameters:\n');
|
||||
fprintf(' - TX Power: %.2f dBm\n', ptx_dbm);
|
||||
fprintf(' - RX Gain: %.1f dB\n', rxPathGain_dB);
|
||||
fprintf(' - System NF: %.1f dB\n', system_NF_dB);
|
||||
fprintf('=============================================\n\n');
|
||||
|
||||
end
|
||||
|
||||
function output_txt = unified_datatip_callback(~, event, ...
|
||||
ax_topview, ax_3d, ax_sideview, ...
|
||||
x_top_m, y_top_m, snr_az_cut, azimuth_deg, ...
|
||||
x_grid_m, y_grid_m, z_grid_m, snr_coverage_2d, elevation_deg, ...
|
||||
x_side_m, z_side_m, snr_el_cut)
|
||||
% Unified datatip callback for all subplots
|
||||
|
||||
try
|
||||
pos = event.Position;
|
||||
current_ax = event.Target.Parent; % Get current axis
|
||||
|
||||
% Determine which subplot was clicked
|
||||
if isequal(current_ax, ax_3d)
|
||||
% 3D Plot
|
||||
x_val = pos(1);
|
||||
y_val = pos(2);
|
||||
z_val = pos(3);
|
||||
|
||||
dist2 = (x_grid_m - x_val).^2 + (y_grid_m - y_val).^2 + (z_grid_m - z_val).^2;
|
||||
[~, nearest_idx] = min(dist2(:));
|
||||
[nearest_el_idx, nearest_az_idx] = ind2sub(size(dist2), nearest_idx);
|
||||
snr_val = snr_coverage_2d(nearest_el_idx, nearest_az_idx);
|
||||
az_val = azimuth_deg(nearest_az_idx);
|
||||
el_val = elevation_deg(nearest_el_idx);
|
||||
|
||||
output_txt = {
|
||||
['x: ' num2str(x_val, '%.3f') ' m']
|
||||
['y: ' num2str(y_val, '%.3f') ' m']
|
||||
['z: ' num2str(z_val, '%.3f') ' m']
|
||||
['Azimuth: ' num2str(az_val, '%.2f') ' deg']
|
||||
['Elevation: ' num2str(el_val, '%.2f') ' deg']
|
||||
['SNR[dB]: ' num2str(snr_val, '%.3f')]
|
||||
};
|
||||
elseif isequal(current_ax, ax_topview)
|
||||
% Top View - x, y, Azimuth, SNR
|
||||
x_val = pos(1);
|
||||
y_val = pos(2);
|
||||
|
||||
[~, nearest_az_idx] = min(abs(x_top_m - x_val).^2 + abs(y_top_m - y_val).^2);
|
||||
az_val = azimuth_deg(nearest_az_idx);
|
||||
snr_val = snr_az_cut(nearest_az_idx);
|
||||
|
||||
output_txt = {
|
||||
['x: ' num2str(x_val, '%.3f') ' m']
|
||||
['y: ' num2str(y_val, '%.3f') ' m']
|
||||
['Azimuth: ' num2str(az_val, '%.2f') ' deg']
|
||||
['SNR[dB]: ' num2str(snr_val, '%.3f')]
|
||||
};
|
||||
elseif isequal(current_ax, ax_sideview)
|
||||
% Side View - x, z, Elevation, SNR
|
||||
x_val = pos(1);
|
||||
z_val = pos(2);
|
||||
|
||||
[~, nearest_el_idx] = min(abs(x_side_m - x_val).^2 + abs(z_side_m - z_val).^2);
|
||||
el_val = elevation_deg(nearest_el_idx);
|
||||
snr_val = snr_el_cut(nearest_el_idx);
|
||||
|
||||
output_txt = {
|
||||
['x: ' num2str(x_val, '%.3f') ' m']
|
||||
['z: ' num2str(z_val, '%.3f') ' m']
|
||||
['Elevation: ' num2str(el_val, '%.2f') ' deg']
|
||||
['SNR[dB]: ' num2str(snr_val, '%.3f')]
|
||||
};
|
||||
else
|
||||
output_txt = 'Unknown plot';
|
||||
end
|
||||
catch ME
|
||||
output_txt = ['Error: ' ME.message];
|
||||
end
|
||||
end
|
||||
|
||||
@@ -119,29 +119,13 @@ 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
|
||||
% 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);
|
||||
|
||||
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
|
||||
% 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'
|
||||
@@ -151,7 +135,14 @@ RadarParams.SP.CFAR.train = [8, 8]; % [doppler, range] training cell 수
|
||||
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 마스크 생성
|
||||
@@ -308,7 +299,7 @@ elevation_deg = [];
|
||||
coverage_info = [];
|
||||
fig_coverage = [];
|
||||
if PlotToggle.coverage
|
||||
[snr_coverage_2d, azimuth_deg, elevation_deg, coverage_info, fig_coverage] = analyze_coverage(RadarParams, 20, 0);
|
||||
[snr_coverage_2d, azimuth_deg, elevation_deg, coverage_info, fig_coverage] = analyze_coverage(RadarParams, RadarParams.Coverage.R_max, RadarParams.Coverage.RCS_dBsm);
|
||||
end
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user