├── AIC.m ├── CSM_CSS.m ├── CSM_TCT.m ├── IMUSIC (frequency Bin) with random phase in same B.svg ├── IMUSIC (frequency Bin) with random phase.svg ├── IMUSIC on each frequency.png ├── IMUSIC(weighted).png ├── IMUSIC-LFM.png ├── IMUSIC.m ├── IMUSIC.png ├── IMUSIC_LFM.m ├── MUSIC.m ├── README.md ├── TCT method in optimal frequency.png ├── TOPS.m ├── Wideband Signal Spectrum(freqBin).png └── temp.png /AIC.m: -------------------------------------------------------------------------------- 1 | function sourceNum = AIC(snapshots, sensorNum, eigVals) 2 | %---sourceNum: the number of sources using AIC method---% 3 | %---snapshots: the number of snapshots------------------% 4 | %---sensorNum: the number of array elements-------------% 5 | %---eigVals: eigen values with descendant sort--------% 6 | t = inf; 7 | for sourceNum = 1: sensorNum - 1 8 | num = 0; 9 | den = 1; 10 | for iter = sourceNum + 1: sensorNum 11 | num = num + eigVals(iter); 12 | den = den * eigVals(iter); 13 | end 14 | Lambda = (num/(sensorNum - sourceNum)) / den^(1/(sensorNum - sourceNum)); 15 | etrpy = 2*snapshots*(sensorNum - sourceNum)*log(Lambda) + ... 16 | 2*sourceNum*(2*sensorNum - sourceNum); % AIC entropy 17 | %-------find minimum loss entropy----------------% 18 | if etrpy > t 19 | break; 20 | else 21 | t = etrpy; 22 | end 23 | end 24 | sourceNum = sourceNum - 1; % fix n 25 | end -------------------------------------------------------------------------------- /CSM_CSS.m: -------------------------------------------------------------------------------- 1 | function [theta, spectrum] = CSM_CSS() 2 | SNR = 15; 3 | sensorNum = 8; 4 | theta_S = [-10; 0]; 5 | sourceNum = length(theta_S); 6 | %----Signal bandwidth: 4MHz, center freq: 10MHz fs: 8e6-----% 7 | f_begin = 8e6; 8 | f_end = 12e6; 9 | bandwidth = f_end - f_begin; 10 | fs = 2*bandwidth; 11 | narrowBandwidth = 1e2; 12 | narrowBandNum = bandwidth/narrowBandwidth; 13 | 14 | freqSnapshots = 200; 15 | nFFT = 64; 16 | 17 | 18 | c = 3e8; 19 | Ts = 1/fs; 20 | snapshots = freqSnapshots*nFFT; 21 | Ns = Ts*(0: snapshots - 1); 22 | margin = (c/f_end)/2; 23 | distance = margin*(0: sensorNum - 1)'; 24 | 25 | receivedData = zeros(sensorNum, snapshots); 26 | manifoldMat = zeros(sensorNum, sourceNum); 27 | signalCovMat = [1, 0; 0, 1]; 28 | for bandNum = 1: narrowBandNum 29 | f = f_begin + (bandNum - 1)*narrowBandwidth; 30 | signalAmp = mvnrnd(zeros(sourceNum, 1), signalCovMat, snapshots).'; 31 | signalMat = [exp(1j*2*pi*f*Ns); exp(1j*2*pi*f*Ns)].*signalAmp; 32 | for col = 1: sourceNum 33 | manifoldMat(:, col) = exp(-1j*2*pi*f*((distance*sind(theta_S(col)))/c)); 34 | end 35 | receivedData = receivedData + manifoldMat*signalMat; 36 | end 37 | receivedData = awgn(receivedData, SNR, 'measured'); 38 | 39 | dataSet = zeros(sensorNum, freqSnapshots, nFFT); 40 | for slice = 1: freqSnapshots 41 | dataSlice = receivedData(:, (slice - 1)*nFFT + 1: slice*nFFT); 42 | for eachSensor = 1: sensorNum 43 | dataSet(eachSensor, slice, :) = fft(dataSlice(eachSensor, :), nFFT); 44 | end 45 | end 46 | 47 | preEstTheta = theta_S + 0.25*randn(); 48 | %---------form tansform matrix-------% 49 | focusFreq = (f_begin + f_end)/2; 50 | % auxiAngles = [-25; -20; -15; 10; 15; 20]; 51 | % focusAuxiManifoldMat = zeros(sensorNum, length(auxiAngles)); 52 | % freqBinManifoldMat = zeros(sensorNum, length(auxiAngles)); 53 | transMat = zeros(sensorNum, sensorNum, nFFT); 54 | preManifoldMat = zeros(sensorNum, sourceNum); 55 | noiseCovMat = zeros(sensorNum, sensorNum); 56 | for col = 1: sourceNum 57 | manifoldMat(:, col) = exp(-1j*2*pi*focusFreq*((distance*sind(preEstTheta(col)))/c)); 58 | end 59 | % for col = 1: length(auxiAngles) 60 | % focusAuxiManifoldMat(:, col) = exp(-1j*2*pi*focusFreq*((distance*sind(auxiAngles(col)))/c)); 61 | % end 62 | for freqPos = 1: nFFT 63 | if freqPos <= nFFT/2 64 | f = fs + (freqPos - 1)*fs/nFFT; 65 | else 66 | f = (f_end + bandwidth) - (freqPos - 1)*fs/nFFT; 67 | end 68 | for col = 1: sourceNum 69 | preManifoldMat(:, col) = exp(-1j*2*pi*f*((distance*sind(preEstTheta(col)))/c)); 70 | end 71 | tempMatB = [zeros(sourceNum, sensorNum - sourceNum); eye(sensorNum - sourceNum)]; 72 | transMat(:, :, freqPos) = [manifoldMat, tempMatB]*pinv([preManifoldMat, tempMatB]); 73 | % for col = 1: length(auxiAngles) 74 | % freqBinManifoldMat(:, col) = exp(-1j*2*pi*f*((distance*sind(auxiAngles(col)))/c)); 75 | % end 76 | % transMat(:, :, freqPos) = [manifoldMat, focusAuxiManifoldMat]*pinv([preManifoldMat, freqBinManifoldMat]); 77 | noiseCovMat = noiseCovMat + transMat(:, :, freqPos)*transMat(:, :, freqPos)'; 78 | end 79 | 80 | %--------prewhite noise covariance matrix--------% 81 | upperMat = chol(noiseCovMat); 82 | 83 | %--------form transformed covarince matrix-------% 84 | transCovMat = zeros(sensorNum, sensorNum); 85 | for freqPos = 1: nFFT 86 | data = dataSet(:, :, freqPos); 87 | covMat = (data*data')/size(data, 2); 88 | transCovMat = transCovMat + transMat(:, :, freqPos)*covMat*transMat(:, :, freqPos)'; 89 | end 90 | transCovMat = pinv(upperMat')*transCovMat*pinv(upperMat); 91 | 92 | %-------MUSIC---------% 93 | [theta, spectrum] = MUSIC(transCovMat, focusFreq, sourceNum, sensorNum, margin); 94 | end -------------------------------------------------------------------------------- /CSM_TCT.m: -------------------------------------------------------------------------------- 1 | function [theta, spectrum] = CSM_TCT() 2 | SNR = 15; 3 | sensorNum = 8; 4 | theta_S = [-10; 0]; 5 | sourceNum = length(theta_S); 6 | %----Signal bandwidth: 4MHz, center freq: 10MHz fs: 8e6-----% 7 | f_begin = 8e6; 8 | f_end = 12e6; 9 | bandwidth = f_end - f_begin; 10 | fs = 2*bandwidth; 11 | narrowBandwidth = 1e2; 12 | narrowBandNum = bandwidth/narrowBandwidth; 13 | 14 | freqSnapshots = 100; 15 | nFFT = 64; 16 | 17 | 18 | c = 3e8; 19 | Ts = 1/fs; 20 | snapshots = freqSnapshots*nFFT; 21 | Ns = Ts*(0: snapshots - 1); 22 | margin = (c/f_end)/2; 23 | distance = margin*(0: sensorNum - 1)'; 24 | 25 | receivedData = zeros(sensorNum, snapshots); 26 | manifoldMat = zeros(sensorNum, sourceNum); 27 | signalCovMat = [1, 0.99; 0.99, 1]; 28 | for bandNum = 1: narrowBandNum 29 | f = f_begin + (bandNum - 1)*narrowBandwidth; 30 | signalAmp = mvnrnd(zeros(sourceNum, 1), signalCovMat, snapshots).'; 31 | signalMat = [exp(1j*2*pi*f*Ns); exp(1j*2*pi*f*Ns)].*signalAmp; 32 | for col = 1: sourceNum 33 | manifoldMat(:, col) = exp(-1j*2*pi*f*((distance*sind(theta_S(col)))/c)); 34 | end 35 | receivedData = receivedData + manifoldMat*signalMat; 36 | end 37 | receivedData = awgn(receivedData, SNR, 'measured'); 38 | 39 | dataSet = zeros(sensorNum, freqSnapshots, nFFT); 40 | for slice = 1: freqSnapshots 41 | dataSlice = receivedData(:, (slice - 1)*nFFT + 1: slice*nFFT); 42 | for eachSensor = 1: sensorNum 43 | dataSet(eachSensor, slice, :) = fft(dataSlice(eachSensor, :), nFFT); 44 | end 45 | end 46 | 47 | preEstTheta = theta_S + 0.25*randn(); 48 | estManifold = zeros(sensorNum, sourceNum); 49 | focusFreqSignalCorreMat = 0; 50 | singularValsSum = 0; 51 | %------form signal correlation matrices and manifold in each frequency bin------% 52 | for freqPos = 1: nFFT 53 | if freqPos <= nFFT/2 54 | f = fs + (freqPos - 1)*fs/nFFT; 55 | else 56 | f = (f_end + bandwidth) - (freqPos - 1)*fs/nFFT; 57 | end 58 | data = dataSet(:, :, freqPos); 59 | covMat = (data*data')/size(data, 2); 60 | [~, eigenVals] = eig(covMat); 61 | eigenVals = diag(eigenVals); 62 | noisePower = min(eigenVals); 63 | cleanedData = covMat - noisePower*eye(sensorNum); 64 | singularValsSum = singularValsSum + svd(cleanedData); 65 | for col = 1: sourceNum 66 | estManifold(:, col) = exp(-1j*2*pi*f*((distance*sind(preEstTheta(col)))/c)); 67 | end 68 | signalCorreMat = pinv(estManifold'*estManifold)*estManifold'*cleanedData*estManifold*pinv(estManifold'*estManifold); 69 | focusFreqSignalCorreMat = focusFreqSignalCorreMat + signalCorreMat; 70 | end 71 | focusFreqSignalCorreMat = focusFreqSignalCorreMat/nFFT; 72 | %------form focus matrices------% 73 | focusFreq = (f_begin + f_end)/2; 74 | focusManifold = zeros(sensorNum, sourceNum); 75 | % cost = inf; 76 | % for freqPos = 1: nFFT/2 77 | % f = fs + (freqPos - 1)*fs/nFFT; 78 | % for col = 1: sourceNum 79 | % focusManifold(:, col) = exp(-1j*2*pi*f*((distance*sind(preEstTheta(col)))/c)); 80 | % end 81 | % focusData = focusManifold*focusFreqSignalCorreMat*focusManifold'; 82 | % thisCost = sum(abs(svd(focusData) - singularValsSum/nFFT).^2); 83 | % if thisCost < cost 84 | % focusFreq = f; 85 | % cost = thisCost; 86 | % end 87 | % end 88 | for col = 1: sourceNum 89 | focusManifold(:, col) = exp(-1j*2*pi*focusFreq*((distance*sind(preEstTheta(col)))/c)); 90 | end 91 | focusData = focusManifold*focusFreqSignalCorreMat*focusManifold'; 92 | [focusEigSubspace, eigenVals] = eig(focusData); 93 | eigenVals = diag(eigenVals); 94 | [~, index] = sort(eigenVals, 'descend'); 95 | focusEigSubspace = focusEigSubspace(:, index); 96 | 97 | covMat_TCT = 0; 98 | for freqPos = 1: nFFT 99 | data = dataSet(:, :, freqPos); 100 | covMat = (data*data')/size(data, 2); 101 | [~, eigenVals] = eig(covMat); 102 | eigenVals = diag(eigenVals); 103 | noisePower = min(eigenVals); 104 | cleanedData = covMat - noisePower*eye(sensorNum); 105 | [eigSubspace, eigenVals] = eig(cleanedData); 106 | eigenVals = diag(eigenVals); 107 | [~, index] = sort(eigenVals, 'descend'); 108 | eigSubspace = eigSubspace(:, index); 109 | transMat = focusEigSubspace*eigSubspace'; 110 | covMat_TCT = covMat_TCT + transMat*cleanedData*transMat'; 111 | end 112 | covMat_TCT = covMat_TCT/nFFT; 113 | 114 | %-------MUSIC---------% 115 | [theta, spectrum] = MUSIC(covMat_TCT, focusFreq, sourceNum, sensorNum, margin); 116 | end -------------------------------------------------------------------------------- /IMUSIC (frequency Bin) with random phase in same B.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -30-25-20-15-10-5051015202530angle/degree-35-30-25-20-15-10-50spectrum/dBIMUSIC 230 | -------------------------------------------------------------------------------- /IMUSIC (frequency Bin) with random phase.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -30-25-20-15-10-5051015202530angle/degree-35-30-25-20-15-10-50spectrum/dBIMUSIC 230 | -------------------------------------------------------------------------------- /IMUSIC on each frequency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unive3sal/DOA-estimation/cfefbdbeb6c7a8dc6ea5da3bfb7592f925f930bb/IMUSIC on each frequency.png -------------------------------------------------------------------------------- /IMUSIC(weighted).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unive3sal/DOA-estimation/cfefbdbeb6c7a8dc6ea5da3bfb7592f925f930bb/IMUSIC(weighted).png -------------------------------------------------------------------------------- /IMUSIC-LFM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unive3sal/DOA-estimation/cfefbdbeb6c7a8dc6ea5da3bfb7592f925f930bb/IMUSIC-LFM.png -------------------------------------------------------------------------------- /IMUSIC.m: -------------------------------------------------------------------------------- 1 | SNR = 15; 2 | sensorNum = 8; 3 | theta_S = [-15, 5]; 4 | sourceNum = length(theta_S); 5 | 6 | f_begin = [600, 1000]; 7 | f_end = [1400, 1400]; 8 | fc = 1000; 9 | bandwidth = f_end - f_begin; 10 | fs = 2*max(bandwidth); 11 | narrowBandwidth = 1; 12 | narrowBandNum = bandwidth/narrowBandwidth; 13 | 14 | freqSnapshots = 100; 15 | nFFT = 256; 16 | snapshots = freqSnapshots*nFFT; 17 | Ts = (1/fs)*(0: snapshots - 1)' + 0.005; 18 | 19 | c = 3e8; 20 | margin = (c/max(f_end))/2; 21 | 22 | test = 0; 23 | 24 | receivedData = zeros(sensorNum, snapshots); 25 | for n = 1: sourceNum 26 | for bandNum = 1: narrowBandNum(n) 27 | f = f_begin(n) + (bandNum - 1)*narrowBandwidth; 28 | steerVec = exp(-1j*2*pi*f*((margin*(0: sensorNum - 1)'*sind(theta_S(n))/c))); 29 | signalVec = exp(1j*2*pi*(f*Ts' + rand())); 30 | test = test + signalVec; 31 | receivedData = receivedData + steerVec*signalVec; 32 | end 33 | end 34 | 35 | receivedData = awgn(receivedData, SNR, 'measured'); 36 | receivedData = receivedData.*exp(-1j*2*pi*fc*Ts'); 37 | test = test.*exp(-1j*2*pi*fc*Ts'); 38 | 39 | dataSet = zeros(sensorNum, freqSnapshots, nFFT); 40 | for slice = 1: freqSnapshots 41 | dataSlice = receivedData(:, (slice - 1)*nFFT + 1: slice*nFFT); 42 | dataSlice = fft(dataSlice, nFFT, 2); 43 | dataSet(:, slice, :) = dataSlice; 44 | end 45 | 46 | theta = (-30: 0.1: 30)'; 47 | spectrum = zeros(size(theta)); 48 | for freqBin = 1: nFFT 49 | if freqBin <= nFFT/2 50 | f = fc + (freqBin - 1)*fs/nFFT; 51 | else 52 | f = (fc - fs) + (freqBin - 1)*fs/nFFT; 53 | end 54 | data = dataSet(:, :, freqBin); 55 | covMat = data*data'/freqSnapshots; 56 | [eigVecs, eigVals] = eig(covMat); 57 | eigVals = diag(eigVals); 58 | [eigVals, index] = sort(eigVals); 59 | sourceNum = AIC(freqSnapshots, sensorNum, flip(eigVals)); 60 | noiseSubspace = eigVecs(:, index(1: sensorNum - sourceNum)); 61 | for n = 1: length(theta) 62 | steerVec = exp(-1j*2*pi*f*(margin*(0: sensorNum - 1)'*sind(theta(n)))/c); 63 | spectrum(n) = spectrum(n) + (steerVec'*steerVec)./... 64 | (steerVec'*(noiseSubspace*noiseSubspace')*steerVec); 65 | end 66 | end 67 | spectrum = spectrum./nFFT; 68 | 69 | plot(theta, 10*log10(abs(spectrum)/max(abs(spectrum)))) 70 | grid on 71 | hold on 72 | for n = 1: length(theta_S) 73 | plot([theta_S(n), theta_S(n)], get(gca, 'YLim'), '--r') 74 | end 75 | hold off 76 | set(gca, 'XTICK', -30: 5: 30) 77 | xlabel('angle/degree') 78 | ylabel('spectrum/dB') 79 | title('IMUSIC') -------------------------------------------------------------------------------- /IMUSIC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unive3sal/DOA-estimation/cfefbdbeb6c7a8dc6ea5da3bfb7592f925f930bb/IMUSIC.png -------------------------------------------------------------------------------- /IMUSIC_LFM.m: -------------------------------------------------------------------------------- 1 | SNR = 15; 2 | sensorNum = 8; 3 | theta_S = [-15, 5]; 4 | sourceNum = length(theta_S); 5 | 6 | f_begin = [600e6, 1000e6]; 7 | f_end = [1400e6, 1400e6]; 8 | fc = 1000e6; 9 | bandwidth = f_end - f_begin; 10 | fs = 2*max(bandwidth); 11 | 12 | freqSnapshots = 100; 13 | nFFT = 256; 14 | snapshots = freqSnapshots*nFFT; 15 | Ts = (1/fs)*(0: snapshots - 1)' + 0.005; 16 | 17 | c = 3e8; 18 | margin = (c/max(f_end))/2; 19 | 20 | receivedData = zeros(sensorNum, snapshots); 21 | for m = 1: sensorNum 22 | for n = 1: sourceNum 23 | delay = (m - 1)*margin*sind(theta_S(n))/c; 24 | k = bandwidth(n)/Ts(end); 25 | % signal = exp(1j*2*pi*(f_begin(n)*Ts + (1/2)*k*Ts.^2)); 26 | receivedData(m, :) = receivedData(m, :) + exp(1j*2*pi*(f_begin(n)*(Ts - delay) + ... 27 | (1/2)*k*(Ts - delay).^2)).'; 28 | end 29 | end 30 | receivedData = awgn(receivedData, SNR, 'measured'); 31 | receivedData = receivedData.*exp(-1j*2*pi*fc*Ts'); 32 | 33 | dataSet = zeros(sensorNum, freqSnapshots, nFFT); 34 | for slice = 1: freqSnapshots 35 | dataSlice = receivedData(:, (slice - 1)*nFFT + 1: slice*nFFT); 36 | dataSlice = fft(dataSlice, nFFT, 2); 37 | dataSet(:, slice, :) = dataSlice; 38 | end 39 | 40 | theta = (-30: 0.1: 30)'; 41 | spectrum = zeros(size(theta)); 42 | for freqBin = 1: nFFT 43 | if freqBin <= nFFT/2 44 | f = fc + (freqBin - 1)*fs/nFFT; 45 | else 46 | f = (fc - fs) + (freqBin - 1)*fs/nFFT; 47 | end 48 | data = dataSet(:, :, freqBin); 49 | covMat = data*data'/freqSnapshots; 50 | [eigVecs, eigVals] = eig(covMat); 51 | eigVals = diag(eigVals); 52 | [eigVals, index] = sort(eigVals); 53 | sourceNum = AIC(freqSnapshots, sensorNum, flip(eigVals)); 54 | noiseSubspace = eigVecs(:, index(1: sensorNum - sourceNum)); 55 | for n = 1: length(theta) 56 | steerVec = exp(-1j*2*pi*f*(margin*(0: sensorNum - 1)'*sind(theta(n)))/c); 57 | spectrum(n) = spectrum(n) + ... 58 | (steerVec'*steerVec)/(steerVec'*(noiseSubspace*noiseSubspace')*steerVec); 59 | end 60 | end 61 | spectrum = spectrum/nFFT; 62 | 63 | plot(theta, 10*log10(abs(spectrum)/max(abs(spectrum)))) 64 | grid on 65 | hold on 66 | for n = 1: length(theta_S) 67 | plot([theta_S(n), theta_S(n)], get(gca, 'YLim'), '--r') 68 | end 69 | hold off 70 | set(gca, 'XTICK', -30: 5: 30) 71 | xlabel('angle/degree') 72 | ylabel('spectrum/dB') 73 | title('IMUSIC-LFM') -------------------------------------------------------------------------------- /MUSIC.m: -------------------------------------------------------------------------------- 1 | function [theta, spectrum] = MUSIC(data, f, sourceNum, sensorNum, margin) 2 | %---@Input: data (x = As + n)------% 3 | %---@ f: frequency (Hz)---% 4 | %---@ sourceNum: number of sources---% 5 | %---@ sensorNum: number of sensors---% 6 | %---@Output: spectrum of MUSIC--% 7 | covMat = (data*data')/size(data, 2); % Covariance matrix 8 | [eigenVec, eigenVals] = eig(covMat); % Eigen factorization 9 | eigenVals = diag(eigenVals); 10 | [~, index] = sort(eigenVals); 11 | noiseSubspace = eigenVec(:, index(1: sensorNum - sourceNum)); 12 | 13 | theta = (-30: 0.1: 30)'; 14 | spectrum = zeros(length(theta), 1); 15 | c = 3e8; 16 | % margin = (c/f)/2; % Let distance between 2 adjacent sensors equal to wavelength/2 17 | for itr = 1: length(theta) 18 | steeringVec = exp(-1j*2*pi*f*(margin*(0: sensorNum - 1)'*sind(theta(itr)))/c); 19 | spectrum(itr) = (steeringVec'*steeringVec)/(steeringVec'*(noiseSubspace*noiseSubspace')*steeringVec); 20 | end 21 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DOA-estimation 2 | DOA estimation source code 3 | http://dengyuhao.org/ -------------------------------------------------------------------------------- /TCT method in optimal frequency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unive3sal/DOA-estimation/cfefbdbeb6c7a8dc6ea5da3bfb7592f925f930bb/TCT method in optimal frequency.png -------------------------------------------------------------------------------- /TOPS.m: -------------------------------------------------------------------------------- 1 | function [theta, spectrum] = TOPS() 2 | SNR = 15; 3 | sensorNum = 8; 4 | theta_S = [-20; 13]; 5 | sourceNum = length(theta_S); 6 | %----Signal bandwidth: 4MHz, center freq: 10MHz fs: 8e6-----% 7 | f_begin = 8e6; 8 | f_end = 12e6; 9 | fc = (f_begin + f_end)/2; 10 | bandwidth = f_end - f_begin; 11 | fs = 2*bandwidth; 12 | narrowBandwidth = 1e2; 13 | narrowBandNum = bandwidth/narrowBandwidth; 14 | 15 | freqSnapshots = 100; 16 | nFFT = 64; 17 | 18 | 19 | c = 3e8; 20 | Ts = 1/fs; 21 | snapshots = freqSnapshots*nFFT; 22 | Ns = Ts*(0: snapshots - 1); 23 | margin = (c/f_end)/2; 24 | distance = margin*(0: sensorNum - 1)'; 25 | 26 | receivedData = zeros(sensorNum, snapshots); 27 | manifoldMat = zeros(sensorNum, sourceNum); 28 | for bandNum = 1: narrowBandNum 29 | f = f_begin + (bandNum - 1)*narrowBandwidth; 30 | signalMat = [exp(-1j*2*pi*f*Ns); exp(-1j*2*pi*f*Ns)]; 31 | for col = 1: sourceNum 32 | manifoldMat(:, col) = exp(-1j*2*pi*f*((distance*sind(theta_S(col)))/c)); 33 | end 34 | receivedData = receivedData + manifoldMat*signalMat; 35 | end 36 | receivedData = awgn(receivedData, SNR, 'measured'); 37 | receivedData = receivedData.*exp(-1j*2*pi*fc*Ns); 38 | 39 | dataSet = zeros(sensorNum, freqSnapshots, nFFT); 40 | for slice = 1: freqSnapshots 41 | dataSlice = receivedData(:, (slice - 1)*nFFT + 1: slice*nFFT); 42 | dataSlice = fft(dataSlice, nFFT, 2); 43 | dataSet(:, slice, :) = dataSlice; 44 | end 45 | 46 | theta = (-30: 0.1: 30)'; 47 | spectrum = zeros(size(theta)); 48 | data = dataSet(:, :, 1); 49 | covMat = (data*data')/size(data, 2); 50 | [eigenVec, eigenVals] = eig(covMat); % Eigen factorization 51 | eigenVals = diag(eigenVals); 52 | [~, index] = sort(eigenVals, 'descend'); 53 | signalSubspace = eigenVec(:, index(1: sourceNum)); 54 | for itr = 1: length(theta) 55 | estimator = []; 56 | for freqPos = 2: nFFT 57 | data = dataSet(:, :, freqPos); 58 | covMat = (data*data')/size(data, 2); 59 | [eigenVec, eigenVals] = eig(covMat); % Eigen factorization 60 | eigenVals = diag(eigenVals); 61 | [~, index] = sort(eigenVals, 'ascend'); 62 | noiseSubspace = eigenVec(:, index(1: sensorNum - sourceNum)); 63 | 64 | if freqPos <= nFFT/2 65 | f = fc + (freqPos - 1)*fs/nFFT; 66 | else 67 | f = (fc - fs) + (freqPos - 1)*fs/nFFT; 68 | end 69 | deltaF = f - fc; 70 | steeringVec = exp(-1j*2*pi*deltaF*(margin*(0: sensorNum - 1)'*sind(theta(itr)))/c); 71 | unitaryMat = diag(steeringVec); 72 | projectionMat = eye(sensorNum) - pinv(steeringVec'*steeringVec)*(steeringVec*steeringVec'); 73 | tempMatU = projectionMat*unitaryMat*signalSubspace; 74 | estimator = [estimator, tempMatU'*noiseSubspace]; 75 | end 76 | singularVals = svd(estimator); 77 | spectrum(itr) = 1/(singularVals(end)); 78 | 79 | end 80 | 81 | end -------------------------------------------------------------------------------- /Wideband Signal Spectrum(freqBin).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unive3sal/DOA-estimation/cfefbdbeb6c7a8dc6ea5da3bfb7592f925f930bb/Wideband Signal Spectrum(freqBin).png -------------------------------------------------------------------------------- /temp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unive3sal/DOA-estimation/cfefbdbeb6c7a8dc6ea5da3bfb7592f925f930bb/temp.png --------------------------------------------------------------------------------