Initial ARSS. Need to improve and add functions.

This commit is contained in:
2026-03-02 14:48:21 +09:00
commit 775668afdb
20 changed files with 1610 additions and 0 deletions
@@ -0,0 +1,159 @@
function fig = visualize_rd_map_with_spurs(target_rd_map, r_axis, v_axis, Target, SpurParams, RadarParams, Slope)
% 2D Range-Doppler .
%
% :
% - target_rd_map: 2D RD [Doppler x Range]
% - r_axis:
% - v_axis:
% - Target: (R, v, NumTargets )
% - SpurParams: (lo, adc, mixer, pulse, lo_leak, clip )
% - RadarParams:
% - Slope: (Hz/s)
%
% :
% - fig: figure
fig = figure('Name', '2D Range-Doppler Map');
imagesc(r_axis, v_axis, 20*log10(abs(target_rd_map)));
axis xy; % y축 ()
colorbar;
xlabel('Range (m)');
ylabel('Velocity (m/s)');
title('Range-Doppler Map (Single Channel)');
colormap(jet);
%
hLines = gobjects(0);
hLabels = {};
% --- 1. ---
hold on;
hTarget = gobjects(0);
if exist('Target','var') && isstruct(Target)
for k = 1:Target.NumTargets
% /
if Target.R(k) < min(r_axis) || Target.R(k) > max(r_axis) || ...
Target.v(k) < min(v_axis) || Target.v(k) > max(v_axis)
continue; %
end
[~, ix] = min(abs(r_axis - Target.R(k)));
[~, iy] = min(abs(v_axis - Target.v(k)));
hTarget(end+1) = plot(r_axis(ix), v_axis(iy), 'ro', 'MarkerSize',8, 'LineWidth',1.5);
text(r_axis(ix), v_axis(iy), sprintf(' T%d', k), 'Color','r','FontSize',8);
end
end
hold off;
%
if exist('hTarget','var') && ~isempty(hTarget)
hLines(end+1) = hTarget(1);
hLabels{end+1} = 'actual target';
end
% --- nonideal/spur ---
show_nonideal_overlay = true;
if exist('SpurParams','var') && isstruct(SpurParams) && isfield(SpurParams,'enabled')
show_nonideal_overlay = logical(SpurParams.enabled);
end
if exist('RadarParams','var') && isstruct(RadarParams) && ...
isfield(RadarParams,'Waveform') && isfield(RadarParams.Waveform,'nonideal')
ni = RadarParams.Waveform.nonideal;
enable_phase_noise = false;
enable_nonlinearity = false;
enable_datasheet_phase_noise = false;
if isfield(ni,'enable_phase_noise')
enable_phase_noise = logical(ni.enable_phase_noise);
end
if isfield(ni,'enable_nonlinearity')
enable_nonlinearity = logical(ni.enable_nonlinearity);
end
if isfield(ni,'phaseNoise') && isstruct(ni.phaseNoise) && isfield(ni.phaseNoise,'enabled')
enable_datasheet_phase_noise = logical(ni.phaseNoise.enabled);
end
show_nonideal_overlay = show_nonideal_overlay && ...
(enable_phase_noise || enable_nonlinearity || enable_datasheet_phase_noise);
end
% --- 2. LO/ADC ---
if show_nonideal_overlay && exist('SpurParams','var') && isstruct(SpurParams)
spur_freqs = [];
spur_names = {};
if isfield(SpurParams,'lo') && ~isempty(SpurParams.lo)
spur_freqs(end+1) = SpurParams.lo.freq;
spur_names{end+1} = 'LO spur';
end
if isfield(SpurParams,'adc') && ~isempty(SpurParams.adc)
spur_freqs(end+1) = SpurParams.adc.freq;
spur_names{end+1} = 'ADC spur';
end
hold on;
for idx = 1:length(spur_freqs)
f = spur_freqs(idx);
name = sprintf('%s @ %.2f MHz', spur_names{idx}, f/1e6);
r_spur = (RadarParams.Basic.c * f) / (2 * Slope);
hLines(end+1) = xline(r_spur, '--m', name);
hLabels{end+1} = name;
end
% --- 3. Pulse comb ---
if isfield(SpurParams,'pulse') && ~isempty(SpurParams.pulse)
p = SpurParams.pulse;
num_harm = 5;
for n = 1:num_harm
f_n = n * p.freq;
r_n = (RadarParams.Basic.c * f_n) / (2 * Slope);
if r_n <= max(r_axis)
lbl = sprintf('pulse comb %d', n);
hLines(end+1) = xline(r_n, '--g', lbl);
hLabels{end+1} = lbl;
end
end
end
% --- 4. Mixer ---
if isfield(SpurParams,'mixer') && ~isempty(SpurParams.mixer) && exist('Target','var')
base_ranges = Target.R;
harmonics = [2,3];
colors = {'--c','--y'};
for hi = 1:length(harmonics)
mul = harmonics(hi);
for r0 = base_ranges
r_spur2 = r0 * mul;
if r_spur2 <= max(r_axis)
lbl = sprintf('mixer x%d', mul);
hLines(end+1) = xline(r_spur2, colors{hi}, lbl);
hLabels{end+1} = lbl;
end
end
end
end
% --- 5. DC offset / LO leakage ---
if isfield(SpurParams,'lo_leak') && ~isempty(SpurParams.lo_leak)
hLines(end+1) = line([min(r_axis), max(r_axis)], [0, 0], 'Color','r','LineStyle',':', 'LineWidth',1.5);
hLabels{end+1} = 'DC offset/LO leak';
end
% --- 6. Clipping spur ---
if isfield(SpurParams,'clip') && ~isempty(SpurParams.clip)
r_clip = SpurParams.clip.range;
if r_clip >= min(r_axis) && r_clip <= max(r_axis)
hLines(end+1) = line([r_clip, r_clip], [min(v_axis), max(v_axis)], 'Color', 'r', 'LineStyle', ':', 'LineWidth', 1.2);
hLabels{end+1} = sprintf('clipping @ %.1f m', r_clip);
end
end
hold off;
end
% --- 7. ---
if ~isempty(hLines)
legend(hLines, hLabels, 'Location', 'northeastoutside');
end
end