Initial Commit.
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
function fd = cal_doppler_shift(va, vb, ra, rb, fc)
|
||||
% va, vb : 각각 물체 a, b의 속도 벡터 [vx vy vz]
|
||||
% ra, rb : 각각 물체 a, b의 위치 벡터 [x y z]
|
||||
% fc : 송신 주파수 (Hz)
|
||||
|
||||
c = 3e8; % 빛의 속도 (m/s)
|
||||
|
||||
% 단위 방향 벡터 r_hat 계산
|
||||
r_ab = rb - ra; % a에서 b로 향하는 벡터
|
||||
r_hat = r_ab / norm(r_ab); % 단위 벡터
|
||||
|
||||
% 속도 차이 벡터 계산
|
||||
v_rel = vb - va;
|
||||
|
||||
% 도플러 시프트 계산
|
||||
fd = (fc / c) * dot(v_rel, r_hat);
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
clear all
|
||||
close all
|
||||
clc
|
||||
|
||||
azi = -90 : 0.1 : 90;
|
||||
elv = -15 : 0.1 : 15;
|
||||
|
||||
% Reference point (origin)
|
||||
x_rdr = 0;
|
||||
y_rdr = 0;
|
||||
z_rdr = 0;
|
||||
|
||||
vx_rdr = 0;
|
||||
vy_rdr = 70/3.6;
|
||||
vz_rdr = 0;
|
||||
|
||||
x_tgt_str = 4;
|
||||
y_tgt_str = -10;
|
||||
z_tgt_str = 0;
|
||||
|
||||
x_tgt_mov = 0;
|
||||
y_tgt_mov = -10;
|
||||
z_tgt_mov = 0;
|
||||
|
||||
vx_tgt_mov = 0;
|
||||
vy_tgt_mov = 1.3905;
|
||||
vz_tgt_mov = 0;
|
||||
|
||||
|
||||
pos_rdr = [x_rdr, y_rdr, z_rdr];
|
||||
vel_rdr = [vx_rdr, vy_rdr, vz_rdr];
|
||||
|
||||
pos_tgt_str = [x_tgt_str, y_tgt_str, z_tgt_str];
|
||||
pos_tgt_mov = [x_tgt_mov, y_tgt_mov, z_tgt_mov];
|
||||
vel_tgt_mov = [vx_tgt_mov, vy_tgt_mov, vz_tgt_mov];
|
||||
vel_tgt_str = [0 0 0];
|
||||
|
||||
rel_r_vec_str = pos_tgt_str - pos_rdr
|
||||
rel_r_vec_mov = pos_tgt_mov - pos_rdr
|
||||
rel_v_vec_mov = vel_tgt_mov - vel_rdr
|
||||
rel_v_vec_str = vel_tgt_str - vel_rdr
|
||||
|
||||
rng_str = norm(rel_r_vec_str)
|
||||
rng_mov = norm(rel_r_vec_mov)
|
||||
rel_vel_mov = rel_v_vec_mov * rel_r_vec_mov'/norm(rel_r_vec_mov)
|
||||
rel_vel_str = rel_v_vec_str * rel_r_vec_str'/norm(rel_r_vec_str)
|
||||
@@ -0,0 +1,46 @@
|
||||
function [worst_scalloping_loss_dB, avg_scalloping_loss_dB, SNR_loss_dB] = cal_winloss(win)
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% Calculating losses of windowing
|
||||
% Start : 23.08.25
|
||||
% End : 23.08.25
|
||||
% developed by Kwanggoo Yeo
|
||||
%
|
||||
% Description
|
||||
% - Input
|
||||
% - 1) win [vector] : window function
|
||||
%
|
||||
% - Output
|
||||
% - 1) worst_scalloping_loss_dB [scalar], [dB] : scalloping loss in worst case
|
||||
% - 2) avg_scalloping_loss_dB [scalar], [dB] : scallopoing loss in average case [uniform distribution]
|
||||
% - 3) SNR_loss_dB [scalar], [dB] : SNR processing gain loss
|
||||
%
|
||||
%
|
||||
% History
|
||||
% (23.08.25) Completed
|
||||
%
|
||||
% Referece
|
||||
% - 1) Mark A. Richards, "Fundamentals of Radar Signal Processing 1st edition", p.257
|
||||
%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
if size(win, 1) > 1
|
||||
win = win.';
|
||||
end
|
||||
|
||||
N = length(win);
|
||||
|
||||
worst_scalloping_loss_dB = mag2db( abs( sum( win .* exp(-1i * pi / N * [0:N-1]))) / sum(win));
|
||||
|
||||
SNR_loss_dB = pow2db( sum(win)^2 / (N * sum(win.^2)) );
|
||||
|
||||
findex = linspace(-pi/N, pi/N, 10000);
|
||||
|
||||
for idx = 1 : length(findex)
|
||||
val(idx) = (abs( sum( win .* exp(-1i * findex(idx) * [0:N-1]))) / sum(win));
|
||||
end
|
||||
avg_scalloping_loss_dB = mag2db(sum(val)/10000);
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
function [peakindex2D, peakval2D] = findpeak2D(data2D, th)
|
||||
|
||||
[Nrow, Ncol] = size(data2D);
|
||||
|
||||
peakindex2D = zeros(Nrow, Ncol);
|
||||
peakval2D = zeros(Nrow, Ncol);
|
||||
|
||||
if isempty(th)
|
||||
for rowidx = 1 : Nrow
|
||||
for colidx = 1 : Ncol
|
||||
indexset = [rowidx-1 colidx; rowidx+1 colidx; rowidx colidx-1; rowidx colidx+1];
|
||||
det_indexset = (indexset(:,1) > 0) .* (indexset(:,1) < Nrow+1) .* (indexset(:,2) > 0) .* (indexset(:,2) < Ncol+1);
|
||||
det_indexset = find(det_indexset > 0);
|
||||
cond_peak = 0;
|
||||
index_iter_len = length(det_indexset);
|
||||
for indexset_idx = 1 : length(det_indexset)
|
||||
if data2D(rowidx, colidx) >= data2D(indexset(det_indexset(indexset_idx),1), indexset(det_indexset(indexset_idx),2))
|
||||
cond_peak = cond_peak + 1;
|
||||
end
|
||||
end
|
||||
|
||||
if cond_peak == index_iter_len
|
||||
peakindex2D(rowidx, colidx) = 1;
|
||||
peakval2D(rowidx, colidx) = data2D(rowidx, colidx);
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for rowidx = 1 : Nrow
|
||||
for colidx = 1 : Ncol
|
||||
indexset = [rowidx-1 colidx; rowidx+1 colidx; rowidx colidx-1; rowidx colidx+1];
|
||||
det_indexset = (indexset(:,1) > 0) .* (indexset(:,1) < Nrow+1) .* (indexset(:,2) > 0) .* (indexset(:,2) < Ncol+1);
|
||||
det_indexset = find(det_indexset > 0);
|
||||
cond_peak = 0;
|
||||
index_iter_len = length(det_indexset);
|
||||
for indexset_idx = 1 : length(det_indexset)
|
||||
if data2D(rowidx, colidx) >= data2D(indexset(det_indexset(indexset_idx),1), indexset(det_indexset(indexset_idx),2))
|
||||
cond_peak = cond_peak + 1;
|
||||
end
|
||||
end
|
||||
|
||||
if cond_peak == index_iter_len && data2D(rowidx, colidx) >= th
|
||||
peakindex2D(rowidx, colidx) = 1;
|
||||
peakval2D(rowidx, colidx) = data2D(rowidx, colidx);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
function fn_add_data_tip(plot_data, name_of_data_tip, data, index)
|
||||
row = dataTipTextRow(name_of_data_tip, data);
|
||||
if ~isa(row.Value, 'double')
|
||||
row.Value = string(row.Value);
|
||||
end
|
||||
plot_data.DataTipTemplate.DataTipRows(index) = row;
|
||||
end
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
function freq_grid = gen_freqgrid(N, Fs, opt)
|
||||
% gen_freqgrid Generate frequency grid
|
||||
% freq_grid = gen_freqgrid(N, Fs, opt) generate an N point
|
||||
% frequency grid according to sample rate Fs. This grid matches
|
||||
% the operation used in fftshift(opt = 1) or not(opt = 0).
|
||||
%
|
||||
% % Example:
|
||||
% % Create a 16 point frequency grid for a sample rate of 10
|
||||
% % Hz used in fftshift.
|
||||
%
|
||||
% freq_grid = gen_freqgrid(16, 10, 1)
|
||||
|
||||
% set 'CenterDC' in psdfreqvec to true preserves Nyquist point,
|
||||
% which does not match our processing to the data since we use
|
||||
% fftshift.
|
||||
|
||||
% adopted from psdfreqvec
|
||||
|
||||
%% Checking 'opt' in input
|
||||
if ~(opt == 0 || opt == 1)
|
||||
disp('Option must be 0(No fftshift) or 1(fftshift)');
|
||||
return;
|
||||
end
|
||||
|
||||
%% Generating freqeuncy grid
|
||||
% freq_grid = fftshift(psdfreqvec(...
|
||||
% 'Npts',N,'Fs',Fs,'Range','whole'));
|
||||
freq_res = Fs/N;
|
||||
freq_grid = (0:N-1).'*freq_res;
|
||||
|
||||
if opt == 1
|
||||
% linspace(freq_offset-fs/2, freq_offset+fs/2*(fft_len-2)/fft_len, fft_len);
|
||||
Nyq = Fs/2;
|
||||
half_res = freq_res/2;
|
||||
if rem(N,2) % odd
|
||||
idx = 1:(N-1)/2;
|
||||
halfpts = (N+1)/2;
|
||||
freq_grid(halfpts) = Nyq-half_res;
|
||||
freq_grid(halfpts+1) = Nyq+half_res;
|
||||
else
|
||||
idx = 1:N/2;
|
||||
hafpts = N/2+1;
|
||||
freq_grid(hafpts) = Nyq;
|
||||
end
|
||||
freq_grid(N) = Fs-freq_res;
|
||||
freq_grid = fftshift(freq_grid);
|
||||
freq_grid(idx) = freq_grid(idx)-Fs;
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,239 @@
|
||||
function [pks,locs_y,locs_x]=peaks2(data,varargin)
|
||||
% Find local peaks in 2D data.
|
||||
% Syntax chosen to be as close as possible to the original Matlab
|
||||
% 'findpeaks' function but not require any additional toolbox.
|
||||
%
|
||||
% SYNTAX:
|
||||
% pks=peaks(data) finds local peaks.
|
||||
%
|
||||
% [pks,locs_y,locs_x]=peaks(data) finds local peaks and their array
|
||||
% coordinates.
|
||||
%
|
||||
% [pks,locs_y,locs_x]=peaks(...,'MinPeakHeight',{scalar value}) only retains
|
||||
% those peaks which are equal to or greater than this absolute value.
|
||||
%
|
||||
% [pks,locs_y,locs_x]=peaks(...,'Threshold',{scalar value}) only retains
|
||||
% those peaks that are higher than their immediate surroundings by this value.
|
||||
%
|
||||
% [pks,locs_y,locs_x]=peaks(...,'MinPeakDistance',{scalar value}) finds peaks
|
||||
% separated by more than the specified minimum CARTESIAN peak distance (a
|
||||
% circle around the peak). It starts from the strongest peak and goes
|
||||
% iteratively lower. Any peak 'shadowed' in the vicinity of a stronger
|
||||
% peak is discarded.
|
||||
%
|
||||
% ALGORITHM:
|
||||
% A peak is considered to be a data point strictly greater than its
|
||||
% immediate neighbors. You can change this condition to 'greater or equal'
|
||||
% in the code, but be aware that in such case, it might create false
|
||||
% detections in flat areas, but these can be accounted for by introduction
|
||||
% of a small Threshold value.
|
||||
%
|
||||
% Even though this function is shared here free for use and any
|
||||
% modifications you might find useful, I would appreciate if you would
|
||||
% quote me in case you are going to use this function for any non-personal
|
||||
% tasks.
|
||||
% (C) Kristupas Tikuisis 2023.
|
||||
|
||||
|
||||
%% Initial data check
|
||||
% Let's simplify the function. Let it work on 1D or 2D data only, and check
|
||||
% if the input data satisfies this criteria:
|
||||
if ~ismatrix(data)
|
||||
error('Only 1D (vectors) or 2D (matrices) data accepted.');
|
||||
end
|
||||
|
||||
|
||||
%% Locate all peaks
|
||||
% A peak is a data point HIGHER than its immediate neighbors. There are 8
|
||||
% around eaxh point, and we will go through each. Oh yes, no escaping that.
|
||||
%
|
||||
% To introduce as little of intermediate variables and keep their memory
|
||||
% footprint as low as possible, I will introduce 2 logical arrays: one to
|
||||
% mark the peaks and be iteratively updated until we check all its
|
||||
% neighbors; and another temporal variable just to prepare data for
|
||||
% comparison (mind about the edge points which do not have any neighbors!):
|
||||
ispeak=false(size(data)); % to store peak flags.
|
||||
isgreater=true(size(data)); % to store comparison result for one particular neighbor.
|
||||
|
||||
% Now start analyzing every data point.
|
||||
%
|
||||
% 1st neighbor immediatelly to the left:
|
||||
ispeak=([true(size(data,1),1) [data(:,2:end)>data(:,1:end-1)]]); % for this case, we can update the peak array directly.
|
||||
%
|
||||
% 2nd neighbor at the top-left:
|
||||
isgreater(2:end,2:end)=(data(2:end,2:end)>data(1:end-1,1:end-1)); % this time, due to points on the diagonal, a temporary array will have to be involved.
|
||||
ispeak=ispeak&isgreater; % time to update the peak array.
|
||||
%
|
||||
% 3rd neighbor immediatelly at the top:
|
||||
ispeak=ispeak&([true(1,size(data,2)); (data(2:end,:)>data(1:end-1,:))]); % once again, for this case, we can update the peak array directly.
|
||||
%
|
||||
% 4th neighbor at the top-right:
|
||||
isgreater=true(size(data)); % rebuild a fresh array for comparison...
|
||||
isgreater(2:end,1:end-1)=(data(2:end,1:end-1)>data(1:end-1,2:end));
|
||||
ispeak=ispeak&isgreater;
|
||||
%
|
||||
% 5th neighbor immediatelly to the right:
|
||||
ispeak=ispeak&([(data(:,1:end-1)>data(:,2:end)) true(size(data,1),1)]); % once again, for this case, we can update the peak array directly.
|
||||
%
|
||||
% 6th neighbor to the bottom-right:
|
||||
isgreater=true(size(data));
|
||||
isgreater(1:end-1,1:end-1)=(data(1:end-1,1:end-1)>data(2:end,2:end));
|
||||
ispeak=ispeak&isgreater;
|
||||
%
|
||||
% 7th neighbor immediatelly at the bottom:
|
||||
ispeak=ispeak&([(data(1:end-1,:)>data(2:end,:)); true(1,size(data,2))]); % once again, for this case, we can update the peak array directly.
|
||||
%
|
||||
% 8th neighbor at the bottom-left:
|
||||
isgreater=true(size(data));
|
||||
isgreater(1:end-1,2:end)=(data(1:end-1,2:end)>data(2:end,1:end-1));
|
||||
ispeak=ispeak&isgreater;
|
||||
%
|
||||
% Discard the temporary variable:
|
||||
clear isgreater
|
||||
% By now, raw peak indentification is completed.
|
||||
|
||||
|
||||
%% Return final results
|
||||
% First, essential raw peak location steps. Peak values and locations:
|
||||
locs=find(ispeak); %clear ispeak
|
||||
pks=data(locs);
|
||||
% Note that LINEAR indices have been returned. Let's turn them to array
|
||||
% indices for final output:
|
||||
[locs_y,locs_x]=ind2sub(size(data),locs);
|
||||
|
||||
|
||||
%% Perform customary post-processing determined by optional function parameters.
|
||||
% First, check if any parameters were supplied:
|
||||
if isempty(varargin)
|
||||
return
|
||||
end
|
||||
% ...then a quality check - the parameters should come in pairs, therefore
|
||||
% the length should be even:
|
||||
if mod(length(varargin),2)~=0
|
||||
warning('Optional name-value parameters should come in pairs. Something is missing. Peak search will proceed with default values.');
|
||||
return
|
||||
end
|
||||
% ...after this step, we can sort the input into names (parameters) and
|
||||
% values:
|
||||
params=varargin(1:2:end);
|
||||
vals=varargin(2:2:end);
|
||||
% ...last quality check - all even values should be CHAR entries specifying
|
||||
% a parameter to be adjusted:
|
||||
ischarparam=cellfun(@ischar,params);
|
||||
if any(~ischarparam)
|
||||
warning('Some parameters are not written as characters and not recognisable. They should always come is name(char)-value pairs. Peak search will proceed with default values.');
|
||||
return
|
||||
end; clear ischarparam varargin
|
||||
|
||||
%--------------------------------------------------------------------------
|
||||
% No go over all supplied parameters and check the found peaks accordingly.
|
||||
|
||||
% 1. MinPeakHeight - absolute minimum value for a peak:
|
||||
isparm=find(cellfun(@(x)isequal(x,'MinPeakHeight'),params),1);
|
||||
if ~isempty(isparm)
|
||||
% Locate which peaks satisfy this condition:
|
||||
suitable=(pks>=vals{isparm});
|
||||
% ...and only keep those:
|
||||
pks=pks(suitable);
|
||||
locs=locs(suitable);
|
||||
clear suitable
|
||||
end
|
||||
|
||||
% 2. Threshold - peak must be greater than its neighbours by this value.
|
||||
isparm=find(cellfun(@(x)isequal(x,'Threshold'),params),1);
|
||||
if ~isempty(isparm)
|
||||
% For this, we will need to convert linear indices to array indices:
|
||||
[row_y,col_x]=ind2sub(size(data),locs);
|
||||
% These will be the original indices.
|
||||
|
||||
% This is how array coordinates would change relatively around each
|
||||
% peak (y,x):
|
||||
% (-1,-1) (-1,0) (-1,+1)
|
||||
% ( 0,-1) ( 0,0) ( 0,+1)
|
||||
% (+1,-1) (+1,0) (+1,+1)
|
||||
% ...turned into vectors disregarding the (0,0), the center data point:
|
||||
delta_y=[-1 -1 -1 0 0 +1 +1 +1];
|
||||
delta_x=[-1 0 +1 -1 +1 -1 0 +1];
|
||||
% Let's add these deltas to the detected peak positions to get the
|
||||
% coordinates of their immediate neighbors:
|
||||
neighbor_locs_y=row_y+delta_y;
|
||||
neighbor_locs_x=col_x+delta_x; clear row_y col_x delta_x delta_y
|
||||
% ...don't forget to check for unrealistic indices beyond array
|
||||
% borders:
|
||||
neighbor_locs_y(neighbor_locs_y<1)=1;
|
||||
neighbor_locs_y(neighbor_locs_y>size(data,1))=size(data,1);
|
||||
neighbor_locs_x(neighbor_locs_x<1)=1;
|
||||
neighbor_locs_x(neighbor_locs_x>size(data,2))=size(data,2);
|
||||
% ...convert to linear indices:
|
||||
neighbor_locs=sub2ind(size(data),neighbor_locs_y,neighbor_locs_x);
|
||||
clear neighbor_locs_y neighbor_locs_x
|
||||
|
||||
% So we have neighbor values by now. Are our peaks higher than those by
|
||||
% the set Threshold value?
|
||||
suitable=(data(locs)-vals{isparm}>=data(neighbor_locs));
|
||||
% Now check for those cases when by mistake (earlier step for checking
|
||||
% for indices beyond array boundaries) a peak itself is taken as a
|
||||
% neighbor as well:
|
||||
suitable(data(neighbor_locs)==data(locs))=true;
|
||||
|
||||
% Only keep those is they are greater than ALL neighbors (in other
|
||||
% words, those elements where NONE are lesser):
|
||||
suitable=~any(~suitable,2); clear neighbor_locs
|
||||
|
||||
% Final step - locate suitable element indices:
|
||||
suitable=find(suitable);
|
||||
|
||||
% That's it, modify the output array:
|
||||
pks=pks(suitable);
|
||||
locs=locs(suitable); clear suitable
|
||||
end
|
||||
|
||||
% 3. 'MinPeakDistance'
|
||||
isparm=find(cellfun(@(x)isequal(x,'MinPeakDistance'),params),1);
|
||||
if ~isempty(isparm)
|
||||
|
||||
% First, sort the peaks in order of amplitude:
|
||||
[pks_sorted,idx]=sort(pks,'descend');
|
||||
locs_sorted=locs(idx); clear idx
|
||||
|
||||
% The flow is as follows: start from the highest peak and discard any
|
||||
% other peaks closer than the CARTESIAN MinPeakDistance (that is, the
|
||||
% CIRCLE around the peak is going to be checked); then continue until
|
||||
% the whole list (updated iteratively as items might get removed) has
|
||||
% been checked.
|
||||
|
||||
% Convert locations to array indices:
|
||||
[row_y,col_x]=ind2sub(size(data),locs_sorted);
|
||||
|
||||
% Start from the highest peak:
|
||||
this_peak=1;
|
||||
while this_peak<(length(pks_sorted)+1)
|
||||
|
||||
% Cartesian distances to ALL its remaining & yet unchecked neighbors
|
||||
% (including itself):
|
||||
dist=sqrt((row_y-row_y(this_peak)).^2+(col_x-col_x(this_peak)).^2);
|
||||
% Now simply check which neighbors are WITHIN the MinPeakDistance
|
||||
% BUT also nonzero (the peak should not be compared to itself):
|
||||
within=( (dist<=vals{isparm}) & (dist~=0) );
|
||||
% ...and delete those entries satisfying the condition:
|
||||
pks_sorted(within)=[];
|
||||
locs_sorted(within)=[];
|
||||
row_y(within)=[]; col_x(within)=[];
|
||||
|
||||
% Update the peak counter:
|
||||
this_peak=this_peak+1;
|
||||
|
||||
end; clear this_peak within dist row_y col_x
|
||||
|
||||
% Update the peak location and value list:
|
||||
pks=pks_sorted;
|
||||
locs=locs_sorted;
|
||||
end
|
||||
|
||||
% I haven't figured out how to do it more elegantly, but turn the default
|
||||
% linear indices to array indices:
|
||||
[locs_y,locs_x]=ind2sub(size(data),locs);
|
||||
|
||||
%==========================================================================
|
||||
% End of the entire function
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
function [del_x, itp_y] = poly2_fit(y_1, y0, y1)
|
||||
|
||||
del_x = -1/2 * ((y1) - (y_1)) / ((y_1) - 2 * (y0) + (y_1));
|
||||
|
||||
itp_y = 1/2 * ((del_x-1) * del_x * (y_1) - 2 * (del_x - 1) * (del_x + 1) * (y0) + (del_x+1) * del_x * (y_1));
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user