1. SNR 신호처리, Secondary surface 영향 고려하여 SNR 재계산

2. Coverage Figure 개선
3. 윈도우 생성 및 성능 계산 함수 추가
This commit is contained in:
2026-03-06 06:48:07 +09:00
parent e002d08580
commit 3c05d2be09
5 changed files with 270 additions and 123 deletions
+129 -74
View File
@@ -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