Initial Commit.

This commit is contained in:
2025-07-29 21:45:44 +09:00
parent a69350b86e
commit 90231d49ae
38 changed files with 2051 additions and 0 deletions
@@ -0,0 +1,24 @@
function [mc_val] = cal_mutual_coherence(dic_mat, plot_flag)
[~, N] = size(dic_mat);
for idx = 1 : N
for jdx = 1 : N
if idx ~= jdx
mc(idx, jdx) = abs(dic_mat(:, idx)' * dic_mat(:, jdx)) / norm(dic_mat(:, idx))^2;
else
mc(idx, jdx) = 0;
end
end
end
if plot_flag == 1
figure
imagesc(mc)
end
mc_val = max(max(mc));
end
@@ -0,0 +1,28 @@
function [sv_ambi_val] = cal_sv_ambi_func(sv_1, sv_2)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Calculting ambiguity(normalized correlation) of two input steering vectors
% Start : 23.08.25
% End : 23.08.25
% developed by Kwanggoo Yeo
%
% Description
% - Input
% - 1) sv_1 [vector], [-] : the first steering vector fc
% - 2) sv_2 [vector], [-] : the second steering vector fc
%
% - Output
% - 1) sv_ambi_val [scalar], [-] : The ambiguity(normalized correlation) of two input steering vectors
%
% History
% (23.08.25) Completed
%
% Referece
% -
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sv_ambi_val = abs(sv_1' * sv_2) / (norm(sv_1) * norm(sv_2));
end
@@ -0,0 +1,44 @@
function [esti_ang_deg, P_MUSIC, test_ang_deg] = df_1D_MUSIC(snapshot, Ntarget, array_struct, fov_deg, unit_ang_deg , plot_flag)
% Number of Snapshots
Nsnap = size(snapshot, 2);
% Estimated Correlation matrix of X
Rx = (1/Nsnap) * (snapshot * snapshot');
% MUSIC algorithm
% Eigen decomposition
[Q, ~, ~] = svd(Rx);
% Noise subspace
Q_n = Q(:, Ntarget+1:end);
% MUSIC algorithm
test_ang_deg = -fov_deg : unit_ang_deg : fov_deg - unit_ang_deg;
P_MUSIC = zeros(1, length(test_ang_deg));
if size(array_struct.eff_ch_loc, 1) == 1
array_struct.eff_ch_loc = array_struct.eff_ch_loc.';
end
Q_n_square = Q_n * Q_n';
for ang_idx = 1 : length(test_ang_deg)
z = exp(1i * 2 * pi / array_struct.lambda_c * array_struct.unit * -sind(test_ang_deg(ang_idx)));
test_sv = z.^array_struct.eff_ch_loc;
P_MUSIC(ang_idx) = 1 / (test_sv' * Q_n_square * test_sv);
end
if plot_flag == 1
figure()
plot(test_ang_deg, pow2db(abs(P_MUSIC)));
grid on
xlabel('Test angle [deg]');
ylabel('Magnitude [dB]');
end
[pks, pks_ang, ~, ~] = findpeaks(pow2db(abs(P_MUSIC)), test_ang_deg);
[~, order] = sort(pks, 'descend');
esti_ang_deg = pks_ang(order(1:Ntarget));
end
+40
View File
@@ -0,0 +1,40 @@
function [esti_ang_deg, P_FT, fft_ang_deg] = df_FFT(snapshot, NFFT, fft_ang, array_struct, Ntarget, plot_flag)
%% FFT algorithm
Nsnap = size(snapshot, 2);
if isempty(fft_ang)
fft_freq = -180 : 360/NFFT : (180 - 360/NFFT);
fft_ang_deg = asind(fft_freq / 2 * array_struct.lambda_c / array_struct.unit / 180);
end
% FFT spectrum
zero_padded_input = complex(zeros(NFFT, Nsnap));
zero_padded_input(array_struct.eff_ch_loc+1, :) = snapshot;
if Nsnap == 1
P_FT = abs(flipud(fftshift((1/Nsnap) * ((fft(zero_padded_input, NFFT)))').')).^2;
else
P_FT = abs(flipud(fftshift((1/Nsnap) * (sum(fft(zero_padded_input, NFFT),2))').')).^2;
end
% Plot
if plot_flag == 1
figure()
plot(fft_ang_deg, pow2db(abs(P_FT)));
grid on
xlabel('Angle [deg]')
ylabel('Magnitude [dB]')
end
[pks, pks_ang, ~, ~] = findpeaks(pow2db(abs(P_FT)), fft_ang_deg);
[~, order] = sort(pks, 'descend');
if isempty(pks)
esti_ang_deg = nan;
else
esti_ang_deg = pks_ang(order(1:Ntarget));
end
end
@@ -0,0 +1,62 @@
function [esti_ang_deg, P_FT, fft_ang_elev_deg, fft_ang_azi_deg] = df_FFT_mar510(zp_snapshot, NFFT_elev, NFFT_azi, fft_ang_elev_deg, fft_ang_azi_deg, array_struct, Ntarget)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Conventioanl Beamforming algorithm for df
% Start : 23.08.25
% End : 23.08.25
% developed by Kwanggoo Yeo
%
% Description
% - Input
% - 1) snapshot [matrix], [-] : raw data(snapshot) for df
% - 2) test_ang_elev_deg [vector], [deg] : elevation angle grid for beamforming
% - 3) test_ang_azi_deg [vector], [deg] : Azimuth angle grid for beamforming
% - 4) lambda_c [scalar], [m] : wavelength of center frequency
% - 4) array_struct [struct], [-] : Structure containing virtual array information
% - 5) Ntarget [scalar], [-] : The number of targets in snapshot
%
% - Output
% - 1) esti_ang_deg [matrix], [deg] : The estimated angles by CBF
% - 2) P_CBF [matrix], [linear] : power spectrum of CBF
%
% History
% (23.08.25) Completed
%
% Referece
% -
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
temp_Nsnap = size(zp_snapshot);
Nsnap = temp_Nsnap(end);
if isempty(fft_ang_elev_deg)
fft_elev_freq = -180 : 360/NFFT_elev : (180 - 360/NFFT_elev);
fft_ang_elev_deg = asind(fft_elev_freq / 2 * array_struct.lambda_c / array_struct.d_unit_elev / 180);
end
if isempty(fft_ang_azi_deg)
fft_azi_freq = -180 : 360/NFFT_azi : (180 - 360/NFFT_azi);
fft_ang_azi_deg = asind(fft_azi_freq / 2 * array_struct.lambda_c / array_struct.d_unit_azi / 180);
end
% FFT spectrum
if Nsnap == 1
P_FT = abs((((1/Nsnap) * ((fft(zero_padded_input, NFFT_azi)))').')).^2;
else
P_FT = abs((fftshift((1/Nsnap) * (sum(fft(zero_padded_input, NFFT_azi),2))').')).^2;
end
[pks, pks_ang, ~, ~] = findpeaks(pow2db(abs(P_FT_2D)), fft_ang_deg);
[~, order] = sort(pks, 'descend');
if isempty(pks)
esti_ang_deg = nan;
else
esti_ang_deg = pks_ang(order(1:Ntarget));
end
end
@@ -0,0 +1,60 @@
function [esti_ang_deg, P_FT, fft_ang_deg] = df_FFT_mar510(snapshot, NFFT, lambda_c, fft_ang, array_struct, Ntarget)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Conventioanl Beamforming algorithm for df
% Start : 23.08.25
% End : 23.08.25
% developed by Kwanggoo Yeo
%
% Description
% - Input
% - 1) snapshot [matrix], [-] : raw data(snapshot) for df
% - 2) test_ang_elev_deg [vector], [deg] : elevation angle grid for beamforming
% - 3) test_ang_azi_deg [vector], [deg] : Azimuth angle grid for beamforming
% - 4) lambda_c [scalar], [m] : wavelength of center frequency
% - 4) array_struct [struct], [-] : Structure containing virtual array information
% - 5) Ntarget [scalar], [-] : The number of targets in snapshot
%
% - Output
% - 1) esti_ang_deg [matrix], [deg] : The estimated angles by CBF
% - 2) P_CBF [matrix], [linear] : power spectrum of CBF
%
% History
% (23.08.25) Completed
%
% Referece
% -
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Nsnap = size(snapshot, 2);
if isempty(fft_ang)
fft_freq = -180 : 360/NFFT : (180 - 360/NFFT);
fft_ang_deg = asind(fft_freq / 2 * lambda_c / array_struct.d_unit / 180);
end
% FFT spectrum
zero_padded_input = complex(zeros(NFFT, Nsnap));
zero_padded_input(flip(abs(array_struct.azi_eff_ch_loc))+1, :) = snapshot;
if Nsnap == 1
%P_FT = abs((fftshift((1/Nsnap) * ((fft(zero_padded_input, NFFT)))').')).^2;
P_FT = abs((((1/Nsnap) * ((fft(zero_padded_input, NFFT)))').')).^2;
else
P_FT = abs((fftshift((1/Nsnap) * (sum(fft(zero_padded_input, NFFT),2))').')).^2;
end
[pks, pks_ang, ~, ~] = findpeaks(pow2db(abs(P_FT)), fft_ang_deg);
[~, order] = sort(pks, 'descend');
if isempty(pks)
esti_ang_deg = nan;
else
esti_ang_deg = pks_ang(order(1:Ntarget));
end
end
+61
View File
@@ -0,0 +1,61 @@
function [esti_ang_deg, P_OMP, test_ang_deg] = df_OMP(snapshot, fov_deg, unit_ang_deg, array_struct, sparsity_val, plot_flag)
test_ang_deg = -fov_deg : unit_ang_deg : fov_deg - unit_ang_deg;
Nant = length(array_struct.eff_ch_loc);
% Spectrum
dic_mat = zeros(Nant, length(test_ang_deg));
for ang_idx = 1 : length(test_ang_deg)
sv = exp(-1i * 2 * pi / array_struct.lambda_c * array_struct.eff_ch_loc.' * array_struct.unit * sind(test_ang_deg(ang_idx)));
dic_mat(:, ang_idx) = sv;
end
mc_val = cal_mutual_coherence(dic_mat, 0)
[N, K] = size(dic_mat); % N:dim of signal, K: # atoms in dictionary
if (N ~= size(snapshot))
error('Dimension not matched');
end
%% Initializing
x = zeros(K,1); % coefficient (output)
r = snapshot; % residual of b
omega = zeros(sparsity_val,1); % selected support
A_omega = []; % corresponding columns of A
cnt = 0;
%% Iteration
while (cnt < sparsity_val) % choose sparsity_val atoms
cnt = cnt+1;
x_tmp = zeros(K,1);
inds = setdiff([1:K],omega); % iterate all columns except for the chosen ones
for idx = inds
x_tmp(idx) = dic_mat(:,idx)' * r / norm(dic_mat(:,idx)); % sol of min ||a'x-b||
end
[~, ichosen] = max(abs(x_tmp)); % choose the maximum
omega(cnt) = ichosen;
A_omega = [A_omega dic_mat(:,ichosen)];
x_ls = A_omega \ snapshot; % Aomega * x_ls = b
r = snapshot - A_omega * x_ls; % update r
end
for idx = 1 : sparsity_val
x(omega(idx)) = x_ls(idx); %x_sparse(i).value;
end
P_OMP = zeros(1, K);
P_OMP(omega) = abs(x_ls).^2;
% Plot
if plot_flag == 1
figure()
plot(test_ang_deg, (P_OMP/max(P_OMP)));
grid on
xlabel('Angle [deg]')
ylabel('Normalized Magnitude [linear]')
end
esti_ang_deg = test_ang_deg(omega);
end
@@ -0,0 +1,5 @@
function [esti_ang_deg] = df_Phase_monopulse(ch1_phase, ch2_phase, ch_distance)
esti_ang_deg = asind((ch1_phase - ch2_phase) / 2 / pi / ch_distance);
end
+67
View File
@@ -0,0 +1,67 @@
function [esti_ang_deg, P_CBF] = df_cbf(snapshot, test_ang_elev_deg, test_ang_azi_deg, lambda_c, array_struct, Ntarget)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Conventioanl Beamforming algorithm for df
% Start : 23.08.25
% End : 23.08.25
% developed by Kwanggoo Yeo
%
% Description
% - Input
% - 1) snapshot [matrix], [-] : raw data(snapshot) for df
% - 2) test_ang_elev_deg [vector], [deg] : elevation angle grid for beamforming
% - 3) test_ang_azi_deg [vector], [deg] : Azimuth angle grid for beamforming
% - 4) lambda_c [scalar], [m] : wavelength of center frequency
% - 4) array_struct [struct], [-] : Structure containing virtual array information
% - 5) Ntarget [scalar], [-] : The number of targets in snapshot
%
% - Output
% - 1) esti_ang_deg [matrix], [deg] : The estimated angles by CBF
% - 2) P_CBF [matrix], [linear] : power spectrum of CBF
%
% History
% (23.08.25) Completed
%
% Referece
% -
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Spectrum
P_CBF = zeros(length(test_ang_elev_deg), length(test_ang_azi_deg));
for ang_elev_idx = 1 : length(test_ang_elev_deg)
for ang_azi_idx = 1 : length(test_ang_azi_deg)
sv = exp(-1i * 2 * pi / lambda_c * ( array_struct.azi_eff_ch_loc.' * array_struct.lambda_c * cosd(test_ang_elev_deg(ang_elev_idx)) * sind(test_ang_azi_deg(ang_azi_idx)) + array_struct.elev_eff_ch_loc.' * array_struct.lambda_c * sind(test_ang_elev_deg(ang_elev_idx))));
P_CBF(ang_elev_idx, ang_azi_idx) = abs((sum(sv'*snapshot))).^2;
end
end
if size(P_CBF, 1) == 1
[pks, pks_ang, ~, ~] = findpeaks(pow2db(abs(P_CBF)), test_ang_azi_deg);
[~, order] = sort(pks, 'descend');
if isempty(pks)
esti_ang_deg = nan;
else
esti_ang_deg = pks_ang(order(1:Ntarget));
end
elseif size(P_CBF, 2) == 1
[pks, pks_ang, ~, ~] = findpeaks(pow2db(abs(P_CBF)), test_ang_elev_deg);
[~, order] = sort(pks, 'descend');
if isempty(pks)
esti_ang_deg = nan;
else
esti_ang_deg = pks_ang(order(1:Ntarget));
end
else
[pks, locs_x, locs_y] = peaks2(pow2db(abs(P_CBF)));
[~, order] = sort(pks, 'descend');
if isempty(pks)
esti_ang_deg = nan;
else
esti_ang_deg = [test_ang_elev_deg(locs_x(order(1:Ntarget))).' test_ang_azi_deg(locs_y(order(1:Ntarget))).'];
end
end
end
@@ -0,0 +1,124 @@
function [snapshot, total_SNR_dB, R_nf, r_m_array, sv_mat, noise] = gen_sig_for_df(fc, target_rng, elev_deg, azi_deg, SNR_dB, txarray_loc, rxarray_loc, Nsnap, ch_error, noise_flag)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Generating raw data(snapshot) for direction finding
% Start : 23.06.01
% End : 23.08.25
% developed by Kwanggoo Yeo
%
% Description
% - Input
% - 1) fc [vector], [Hz] : Center freqeuncy of radar Tx signal
% - 2) target_rng [vector], [m] : Distance(range) from the radar to each target
% - 3) elev_deg [vector], [deg] : Elevation angle for each taret
% - 4) azi_deg [vector], [deg] : Azimuth angle for each taret
% - 5) SNR_dB [vector], [dB] : SNR for each taret
% - 6) txarray_loc [matrix], [m] : Locations of txarray elements in cartesian coordinate
% - 7) rxarray_loc [matrix], [m] : Locations of rxarray elements in cartesian coordinate
% - 8) Nsnap [scalar], [-] : The number of snapshots to generate
% - 9) ch_error [vector], [-] : gain & phase error for each element in virtual array
% - 10) noise_flag [scalar], [-] : Flag for noise which is included in snapshot (1) or not (0)
%
% - Output
% - 1) snapshot [matrix], [-] : Generated raw data(snapshot)
% - 2) total_SNR_dB [scalar], [dB] : SNR of snapshot, not SNR of signal in single element
% - 3) R_nf [scalar], [m] : Distance of near-field (Frensel Region)
% - 4) r_m_array [matrix], [m] : Distance from the targets to each element in virtual array
% - 5) sv_amt [matrix], [-] : Steering matrix
% - 6) noise [matrix], [-] : Generated noise in each element in virtual array
%
% History
% (23.08.25) Completed
%
% Referece
% -
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Assumptions
%
% 1. Non-dispersion medium
% 2. Narrowband
% 3. No assumption on Near/Far-field
% 4. Geometry
% 4-1. Cartesian(x-y-z) , local coordinate
% 4-2. Elevation angle : x-y : + , : -
% 4-3. Azimuth angle : x-y , x축의 : +, : -
% 4-4. Virtual array (tx1, rx1) (coordinate origin)
% 4-5. x축 : boresignt
% 5. Monostatic radar system
%% Basic constants settings
c0 = physconst('LightSpeed');
lambda_c = c0/fc;
k_c = 2*pi / lambda_c;
Np = length(azi_deg); % Number of targets
% ch_error must be column vector
if size(ch_error, 1) == 1
ch_error = ch_error.';
end
%% Array settings
Nt = size(txarray_loc, 2);
Nr = size(rxarray_loc, 2);
% Near field region calcuation
array_dist = zeros(Nt*Nr, 1);
for txidx = 1 : Nt
for rxidx = 1 : Nr
array_dist(Nr*(txidx-1) + rxidx) = sqrt(sum((txarray_loc(:,txidx) - rxarray_loc(:,rxidx)).^2));
end
end
max_len_array = max(array_dist);
R_nf = 2 * max_len_array^2 / lambda_c;
% Target location calcuation in Cartesian
target_loc = zeros(3, Np);
for tidx = 1 : Np
target_loc(:, tidx) = [target_rng(tidx)*cosd(elev_deg(tidx))*sind(azi_deg(tidx)) ; target_rng(tidx)*cosd(elev_deg(tidx))*cosd(azi_deg(tidx)); target_rng(tidx)*sind(elev_deg(tidx))];
end
% Generating steering vector(sv) matrix
r_m_array = complex(zeros(Nt*Nr, Np));
sv_mat = complex(zeros(Nt*Nr, Np));
for target_idx = 1 : Np
for txarray_idx = 1 : Nt
for rxarray_idx = 1 : Nr
r_m_array(Nr*(txarray_idx-1)+rxarray_idx, target_idx) = sqrt(sum((txarray_loc(:, txarray_idx) - target_loc(:, target_idx)).^2)) + sqrt(sum((rxarray_loc(:, rxarray_idx) - target_loc(:, target_idx)).^2));
sv_mat(Nr*(txarray_idx-1)+rxarray_idx, target_idx) = exp(1i * k_c * r_m_array(Nr*(txarray_idx-1)+rxarray_idx, target_idx));
end
end
sv_mat(:, target_idx) = sv_mat(:, target_idx) .* ch_error;
sv_mat(:, target_idx) = sv_mat(:, target_idx) * conj(sv_mat(1, target_idx));
end
%% Signal Generation
% Calculating signal complex gain baed on SNR_dB
noise = (sqrt(0.5) * (randn(Nt*Nr, Nsnap) + 1i * randn(Nt*Nr, Nsnap)));
Pn = sum(diag(noise * noise')/Nsnap) / (Nt*Nr);
sig = zeros(Np, Nsnap);
for target_idx = 1 : Np
Ps = 10^(SNR_dB(target_idx)/10) * Pn;
sig(target_idx, :) = sqrt(Ps) * exp(1i * 2 * pi * rand(1, Nsnap));
end
% Signal model
if noise_flag == 1
snapshot = sv_mat * sig + noise;
else
snapshot = sv_mat * sig;
end
% Total SNR_dB
Ps_total = sum(diag((sv_mat * sig) * (sv_mat * sig)')/Nsnap) / (Nt*Nr);
total_SNR_dB = 10 * log10( Ps_total / Pn );
end
@@ -0,0 +1,36 @@
function [mimoarray] = gen_virarray(txarray_loc, rxarray_loc)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Generating MIMO virtual array
% Start : 23.08.25
% End : 23.08.25
% developed by Kwanggoo Yeo
%
% Description
% - Input
% - 1) txarray_loc [matrix], [m] : Locations of txarray elements in cartesian coordinate
% - 2) rxarray_loc [matrix], [m] : Locations of rxarray elements in cartesian coordinate
%
% - Output
% - 1) mimoarray [matrix], [m] : virtual array
%
% History
% (23.08.25) Completed
%
% Referece
% -
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Nt = size(txarray_loc,2);
Nr = size(rxarray_loc,2);
mimoarray = zeros(3, Nt*Nr);
for tx_idx = 1 : Nt
for rx_idx = 1 : Nr
mimoarray(:, Nr*(tx_idx-1) + rx_idx) = txarray_loc(:, tx_idx) + rxarray_loc(:, rx_idx);
end
end
end