├── P_1.mat ├── conf_search.m ├── dinkelbach.m ├── directive_search.m ├── linear_amb.m ├── linear_iso.m ├── linear_iso_search.m ├── planar_compare.m ├── planar_direc.m ├── planar_iso.m └── planar_search_n.m /P_1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiangrong-lab/DOA-estimation/739db082f5095b497d894fcca5b6b75464c6765e/P_1.mat -------------------------------------------------------------------------------- /conf_search.m: -------------------------------------------------------------------------------- 1 | %optimum subarray versus the elevation angle 2 | clear; 3 | clc; 4 | 5 | N1 = 5; 6 | N2 = 5; 7 | K = 10; 8 | lambda = 1; 9 | d = lambda/2; 10 | k0 = 2*pi/lambda; 11 | n = -(N1-1)/2:1:(N1-1)/2; 12 | m = [-(N2-1)/2:1:(N2-1)/2]'; 13 | mn = []; 14 | for i = 1:N1 15 | mn = [mn;[n(i)*ones(N2,1),m]]; %mn is the position vector of N*N/2 by 2 dimension 16 | end 17 | 18 | %define the array position matrix 19 | dx = d*mn(:,1); 20 | dy = d*mn(:,2); 21 | dxx = dx.*dx; 22 | dyy = dy.*dy; 23 | dxy = dx.*dy; 24 | 25 | %generate the arraival direction 26 | theta_s = 10*pi/180; 27 | phi_s = [0:1:180]*pi/180; 28 | P_o = zeros(K,2,length(phi_s)); 29 | 30 | 31 | for i = 1:length(phi_s) 32 | 33 | alpha = (sin(phi_s(i))^2)/(cos(theta_s)^2)+(cos(phi_s(i))^2)/(sin(theta_s)^2); 34 | beta = (cos(phi_s(i))^2)/(cos(theta_s)^2)+(sin(phi_s(i))^2)/(sin(theta_s)^2); 35 | zeta = (sin(2*phi_s(i)))/(sin(theta_s)^2)-(sin(2*phi_s(i)))/(cos(theta_s)^2); 36 | x_o = directive_search(dxx,dx,dyy,dy,dxy,K,N1*N2,alpha,beta,zeta); 37 | 38 | index = 1; 39 | for k = 1:N1*N2 40 | if (abs(x_o(k)-1)<=0.1) 41 | P_o(index,:,i) = mn(k,:); 42 | index = index + 1; 43 | end 44 | end 45 | end 46 | 47 | save('P_o.mat','P_o'); 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /dinkelbach.m: -------------------------------------------------------------------------------- 1 | function w0 = dinkelbach(dxx,dx,dyy,dy,dxy,K,N,alpha,beta,zeta,eta) 2 | 3 | %compose matrix A and B 4 | A = (alpha/K)*dxx*ones(1,N)+(beta/K)*dyy*ones(1,N) + (zeta/K)*dxy*ones(1,N); 5 | B = dxx*dyy'-dxy*dxy'; 6 | F = 1; 7 | kesi = 0.01; 8 | ee = ones(N,1); 9 | 10 | while(abs(F) > kesi) 11 | cvx_begin 12 | variable W(N,N); variable w(N,1); 13 | minimize (trace(W*(A-eta*B))); 14 | subject to 15 | 0 <= w'*dx <= 0; 16 | 0 <= w'*dy <= 0; 17 | K <= w'*ee <= K; 18 | [W,w;w',1] == semidefinite(N+1); 19 | for k = 1:N 20 | e = [zeros(k-1,1);ones(1,1);zeros(N-k,1)]; 21 | E = e*e'; 22 | 0 <= trace(W*E)-e'*w <= 0; 23 | end 24 | cvx_end 25 | F = trace(W*(A-eta*B)); 26 | eta = trace(W*A)/trace(W*B); 27 | 28 | end 29 | [Ys,Is] = sort(w,'descend'); 30 | w0 = zeros(N,1); 31 | w0(Is(1:K))=1; 32 | end 33 | -------------------------------------------------------------------------------- /directive_search.m: -------------------------------------------------------------------------------- 1 | function x0 = directive_search(dxx,dx,dyy,dy,dxy,K,N,alpha,beta,zeta) 2 | id = 1:N; 3 | V = nchoosek(id,K); 4 | num = nchoosek(N,K); 5 | e = ones(K,1); 6 | %searching 7 | y = zeros(num,1); 8 | for i = 1:num 9 | if ((e'*dx(V(i,:))==0) && (e'*dy(V(i,:))==0)) 10 | y(i) = (e'*dxx(V(i,:))*e'*dyy(V(i,:))-e'*dxy(V(i,:))*e'*dxy(V(i,:)))... 11 | /(alpha*e'*dxx(V(i,:))+beta*e'*dyy(V(i,:))+zeta*e'*dxy(V(i,:))); 12 | end 13 | end 14 | [ymax,Imax] = max(y); 15 | x0 = zeros(N,1); 16 | for i = 1:K 17 | x0(V(Imax,i)) = 1; 18 | end 19 | end 20 | 21 | -------------------------------------------------------------------------------- /linear_amb.m: -------------------------------------------------------------------------------- 1 | function x0 = linear_amb(V,dxx,dx,K,N,delta) 2 | e = ones(N,1); 3 | mu = 10; 4 | Q = 4; 5 | x0 = [ones(K/2,1);zeros(N-K,1);ones(K/2,1)]; 6 | for q = 1:Q 7 | cvx_begin 8 | variable x(N); 9 | minimize (-x'*dxx+mu*(e'*x-2*x0'*x)); 10 | subject to 11 | 0 <= x'*dx <= 0; 12 | K <= e'*x <= K; 13 | 0 <= x <= 1; 14 | for i = 1:size(V,2) 15 | W = (1/(K*K))*real(V(:,i)*V(:,i)'); 16 | x'*W*x <= delta; 17 | end 18 | cvx_end 19 | x0 = x; 20 | end 21 | end -------------------------------------------------------------------------------- /linear_iso.m: -------------------------------------------------------------------------------- 1 | %optimum isotorpic array 2 | clear; 3 | clc; 4 | 5 | N = 20; 6 | K = 10; 7 | n = -(N-1)/2:1:(N-1)/2; 8 | id = 1:N; 9 | lambda = 1; 10 | d = lambda/2; 11 | k0 = 2*pi/lambda; 12 | 13 | %define the array position matrix 14 | dx = d*n'; 15 | dxx = dx.*dx; 16 | 17 | %avoiding ambiguity 18 | vjs1 = exp(1i*k0*d*n'*0.12); 19 | vjs2 = exp(1i*k0*d*n'*0.24); 20 | vjs3 = exp(1i*k0*d*n'*0.36); 21 | vjs4 = exp(1i*k0*d*n'*0.48); 22 | W = [vjs1,vjs2,vjs3,vjs4]; 23 | delta = 0.2; 24 | % x_am = linear_amb(W,dxx,dx,K,N,delta); 25 | x_am = linear_iso_search(W,dxx,dx,K,N,delta); 26 | %calculate the position 27 | P_am = zeros(K,1); 28 | index = 1; 29 | for i = 1:N 30 | if (abs(x_am(i)-1)<=0.4) 31 | P_am(index) = n(i); 32 | index = index + 1; 33 | end 34 | end 35 | %optimum isotropic array without considering ambiguity 36 | x_o = [ones(K/2,1);zeros(N-K,1);ones(K/2,1)]; 37 | P_o = zeros(K,1); 38 | index = 1; 39 | for i = 1:N 40 | if (abs(x_o(i)-1)<=0.4) 41 | P_o(index) = n(i); 42 | index = index + 1; 43 | end 44 | end 45 | 46 | %compare beampatterns 47 | vs_o = exp(-1i*k0*d*P_o*0); 48 | vs_am = exp(-1i*k0*d*P_am*0); 49 | theta = 0:0.5:180; 50 | u = cos(theta*pi/180); 51 | v = exp(1i*k0*d*P_o*u); 52 | figure; 53 | plot(theta,20*log10(abs(vs_o'*v)/max(abs(vs_o'*v)))); 54 | hold on; 55 | v = exp(1i*k0*d*P_am*u); 56 | plot(theta,20*log10(abs(vs_am'*v)/max(abs(vs_am'*v))),'k'); 57 | 58 | %calculate the estimation variance 59 | snr = -5:1:30; %signal to noise ratio 60 | T = 1; %the number of snapshots 61 | theta_search = 0:0.0005:pi; 62 | V_o = exp(1i*k0*d*P_o*cos(theta_search)); 63 | V_am = exp(1i*k0*d*P_am*cos(theta_search)); 64 | V_ula = exp(1i*k0*d*n'*cos(theta_search)); 65 | Q = 500;%Q Monte-Carlo runs 66 | 67 | mse_o = zeros(length(snr),1); 68 | mse_am = zeros(length(snr),1); 69 | mse_ula = zeros(length(snr),1); 70 | 71 | %generate the arraival direction 72 | theta_s = pi/3; 73 | vs_o = exp(1i*k0*d*P_o*cos(theta_s)); 74 | vs_am = exp(1i*k0*d*P_am*cos(theta_s)); 75 | %ULA 76 | vs_ula = exp(1i*k0*d*n'*cos(theta_s)); 77 | 78 | for q = 1:length(snr) 79 | variance_o = 0; 80 | variance_am = 0; 81 | variance_ula = 0; 82 | for i = 1:Q 83 | %generate the estimated signal 84 | X = (randn(1,T) + 1i * randn(1,T)) / sqrt(2); 85 | Y_o = vs_o * X; 86 | Y_am = vs_am * X; 87 | Y_ula = vs_ula * X; 88 | % generate the white noise 89 | sigma_o = 10^(-snr(q)/10) * (norm(Y_o,'fro')^2) / (K * T); 90 | sigma_am = 10^(-snr(q)/10) * (norm(Y_am,'fro')^2) / (K * T); 91 | sigma_ula = 10^(-snr(q)/10) * (norm(Y_ula,'fro')^2) / (N * T); 92 | % noise 93 | E_o = sqrt(sigma_o)/sqrt(2)*randn(K,T) + 1i*sqrt(sigma_o)/sqrt(2)*randn(K,T); 94 | E_am = sqrt(sigma_am)/sqrt(2)*randn(K,T) + 1i*sqrt(sigma_am)/sqrt(2)*randn(K,T); 95 | E_ula = sqrt(sigma_ula)/sqrt(2)*randn(N,T) + 1i*sqrt(sigma_ula)/sqrt(2)*randn(N,T); 96 | %received signal 97 | Y_o = Y_o + E_o; 98 | Y_am = Y_am + E_am; 99 | Y_ula = Y_ula + E_ula; 100 | %DOA estimation 101 | y_o = abs(V_o'*Y_o); 102 | y_am = abs(V_am'*Y_am); 103 | y_ula = abs(V_ula'*Y_ula); 104 | [y_m1,I_max] = max(y_o); 105 | theta_est_o = theta_search(I_max); 106 | [y_m2,I_max] = max(y_am); 107 | theta_est_am = theta_search(I_max); 108 | [y_m3,I_max] = max(y_ula); 109 | theta_est_ula = theta_search(I_max); 110 | %variance 111 | variance_o = variance_o + (theta_est_o-theta_s)^2; 112 | variance_am = variance_am + (theta_est_am-theta_s)^2; 113 | variance_ula = variance_ula + (theta_est_ula-theta_s)^2; 114 | end 115 | mse_o(q) = variance_o/Q; 116 | mse_am(q) = variance_am/Q; 117 | mse_ula(q) = variance_ula/Q; 118 | end 119 | 120 | %array without ambiguity solved 121 | e = ones(1,K); 122 | figure; 123 | plot(snr,10*log10(mse_o)); 124 | hold on; 125 | rho = 10.^(snr/10); 126 | mse_ot= (1+K*rho)./(2*K*(rho.^2)*(4*pi*pi/lambda/lambda)*(sin(theta_s)^2)*d*d*(e*(P_o.^2))); 127 | plot(snr,10*log10(mse_ot),'k'); 128 | 129 | %array with ambiguity solved 130 | hold on; 131 | plot(snr,10*log10(mse_am),'g'); 132 | hold on; 133 | mse_amt= (1+K*rho)./(2*K*(rho.^2)*(4*pi*pi/lambda/lambda)*(sin(theta_s)^2)*d*d*(e*(P_am.^2))); 134 | plot(snr,10*log10(mse_amt),'y'); 135 | 136 | %ULA 137 | hold on; 138 | plot(snr,10*log10(mse_ula),'r'); 139 | hold on; 140 | mse_ulat= (1+N*rho)./(2*N*(rho.^2)*(4*pi*pi/lambda/lambda)*(sin(theta_s)^2)*d*d*((n.^2)*ones(N,1))); 141 | plot(snr,10*log10(mse_ulat),'c'); 142 | 143 | -------------------------------------------------------------------------------- /linear_iso_search.m: -------------------------------------------------------------------------------- 1 | function x0 = linear_search(W,dxx,dx,K,N,delta) 2 | id = 1:N; 3 | V = nchoosek(id,K); 4 | num = nchoosek(N,K); 5 | e = ones(K,1); 6 | %searching 7 | y = zeros(num,1); 8 | for i = 1:num 9 | if (e'*dx(V(i,:))==0) 10 | flag = 0; 11 | for k = 1:size(W,2) 12 | v = W(:,k); 13 | if ((1/K)*abs(v(V(i,:))'*e) <= delta) 14 | flag = flag + 1; 15 | end 16 | end 17 | if (flag == size(W,2)) 18 | y(i) = e'*dxx(V(i,:)); 19 | end 20 | end 21 | end 22 | [ymax,Imax] = max(y); 23 | x0 = zeros(N,1); 24 | for i = 1:K 25 | x0(V(Imax,i)) = 1; 26 | end 27 | end 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /planar_compare.m: -------------------------------------------------------------------------------- 1 | %optimum subarray versus the elevation angle 2 | clear; 3 | clc; 4 | 5 | N1 = 5; 6 | N2 = 5; 7 | K = 10; 8 | lambda = 1; 9 | d = lambda/2; 10 | k0 = 2*pi/lambda; 11 | n = -(N1-1)/2:1:(N1-1)/2; 12 | m = [-(N2-1)/2:1:(N2-1)/2]'; 13 | mn = []; 14 | for i = 1:N1 15 | mn = [mn;[n(i)*ones(N2,1),m]]; %mn is the position vector of N*N/2 by 2 dimension 16 | end 17 | 18 | %define the array position matrix 19 | dx = d*mn(:,1); 20 | dy = d*mn(:,2); 21 | dxx = dx.*dx; 22 | dyy = dy.*dy; 23 | dxy = dx.*dy; 24 | 25 | %generate the arraival direction 26 | theta_s = 10*pi/180; 27 | phi_s = [0:1:180]*pi/180; 28 | 29 | snr = 10; %signal to noise ratio 30 | 31 | %read the optimum configuration corresponding to each azimuth angle 32 | load('P_1.mat'); 33 | 34 | e = ones(1,K); 35 | rho = 10^(snr/10); 36 | 37 | mse_theta_ot = zeros(length(phi_s),1); 38 | mse_phi_ot = zeros(length(phi_s),1); 39 | 40 | for i = 1:length(phi_s) 41 | 42 | P_o = P_1(:,:,i); 43 | 44 | mse_theta_ot(i) = (1+K*rho)./(2*K*(rho.^2)*(4*pi*pi/lambda/lambda)*(cos(theta_s).^2))... 45 | *(d*d*e*(P_o(:,1).^2)*(sin(phi_s(i)).^2)+d*d*e*(P_o(:,2).^2)*(cos(phi_s(i)).^2)... 46 | -d*d*e*(P_o(:,1).*P_o(:,2))*sin(2*phi_s(i)))/(d*d*e*(P_o(:,1).^2)*d*d*e*(P_o(:,2).^2)... 47 | -d*d*e*(P_o(:,1).*P_o(:,2))*d*d*e*(P_o(:,1).*P_o(:,2))); 48 | mse_phi_ot(i) = (1+K*rho)./(2*K*(rho.^2)*(4*pi*pi/lambda/lambda)*(sin(theta_s).^2))... 49 | *(d*d*e*(P_o(:,1).^2)*(cos(phi_s(i)).^2)+d*d*e*(P_o(:,2).^2)*(sin(phi_s(i)).^2)... 50 | +d*d*e*(P_o(:,1).*P_o(:,2))*sin(2*phi_s(i)))/(d*d*e*(P_o(:,1).^2)*d*d*e*(P_o(:,2).^2)... 51 | -d*d*e*(P_o(:,1).*P_o(:,2))*d*d*e*(P_o(:,1).*P_o(:,2))); 52 | end 53 | plot(phi_s*180/pi,10*log10(mse_phi_ot+mse_theta_ot),'c'); 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /planar_direc.m: -------------------------------------------------------------------------------- 1 | %optimum directive planar array 2 | clear; 3 | clc; 4 | 5 | N1 = 4; 6 | N2 = 6; 7 | K = 10; 8 | n = -(N1-1)/2:1:(N1-1)/2; 9 | m = [-(N2-1)/2:1:(N2-1)/2]'; 10 | mn = []; 11 | for i = 1:N1 12 | mn = [mn;[n(i)*ones(N2,1),m]]; %mn is the position vector of N*N/2 by 2 dimension 13 | end 14 | lambda = 1; 15 | d = lambda/2; 16 | k0 = 2*pi/lambda; 17 | 18 | %define the array position matrix 19 | dx = d*mn(:,1); 20 | dy = d*mn(:,2); 21 | dxx = dx.*dx; 22 | dyy = dy.*dy; 23 | dxy = dx.*dy; 24 | 25 | %generate the arraival direction 26 | theta_s = 10*pi/180; 27 | phi_s = 175*pi/180; 28 | ux_s = sin(theta_s)*cos(phi_s); 29 | uy_s = sin(theta_s)*sin(phi_s); 30 | 31 | %optimum isotropic array with ambiguity 32 | alpha = (sin(phi_s)^2)/(cos(theta_s)^2)+(cos(phi_s)^2)/(sin(theta_s)^2); 33 | beta = (cos(phi_s)^2)/(cos(theta_s)^2)+(sin(phi_s)^2)/(sin(theta_s)^2); 34 | zeta = (sin(2*phi_s))/(sin(theta_s)^2)-(sin(2*phi_s))/(cos(theta_s)^2); 35 | % x_o = directive_search(dxx,dx,dyy,dy,dxy,K,N1*N2,alpha,beta,zeta); 36 | eta = 4.56; 37 | x_o = dinkelbach(dxx,dx,dyy,dy,dxy,K,N1*N2,alpha,beta,zeta,eta); 38 | P_o = zeros(K,2); 39 | index = 1; 40 | for i = 1:N1*N2 41 | if (abs(x_o(i)-1)<=0.4) 42 | P_o(index,:) = mn(i,:); 43 | index = index + 1; 44 | end 45 | end 46 | % %plot the selected subarray 47 | % spy(fliplr(reshape(x_o,5,5)')'); 48 | 49 | %compare beampatterns 50 | theta = 0:0.02:pi/2; 51 | phi = 0:0.02:2*pi; 52 | %steering vector of the desired signal 53 | vs_o = exp(1i*k0*d*P_o*[ux_s;uy_s]); 54 | Y_o = zeros(length(theta),length(phi)); 55 | for i = 1:length(theta) 56 | for k = 1:length(phi) 57 | ux = sin(theta(i))*cos(phi(k)); 58 | uy = sin(theta(i))*sin(phi(k)); 59 | v = exp(1i*k0*d*P_o*[ux;uy]); 60 | Y_o(i,k) = abs(vs_o'*v); 61 | end 62 | end 63 | [X,Y] = meshgrid(phi,theta); 64 | mesh(X,Y,Y_o); 65 | 66 | %calculate the estimation variance 67 | snr = -5:1:30; %signal to noise ratio 68 | T = 1; %the number of snapshots 69 | Q = 500;%Q Monte-Carlo runs 70 | %searching grid points 71 | theta = 0:0.002:pi/2; 72 | phi = 0:0.002:2*pi; 73 | ux = sin(theta')*cos(phi); 74 | uy = sin(theta')*sin(phi); 75 | u_search = [ux(:)';uy(:)']; 76 | 77 | mse_theta_o = zeros(length(snr),1); 78 | mse_phi_o = zeros(length(snr),1); 79 | 80 | for q = 1:length(snr) 81 | variance_theta_o = 0; 82 | variance_phi_o = 0; 83 | for i = 1:Q 84 | %generate the estimated signal 85 | X = (randn(1,T) + 1i * randn(1,T)) / sqrt(2); 86 | Y_o = vs_o * X; 87 | % generate the white noise 88 | sigma_o = 10^(-snr(q)/10) * (norm(Y_o,'fro')^2) / (K * T); 89 | % noise 90 | E_o = sqrt(sigma_o)/sqrt(2)*randn(K,T) + 1i*sqrt(sigma_o)/sqrt(2)*randn(K,T); 91 | %received signal 92 | Y_o = Y_o + E_o; 93 | %DOA estimation 94 | v_o = exp(1i*k0*d*P_o*u_search); 95 | y_o = abs(v_o'*Y_o); 96 | %searching the peak 97 | [y_m1,I_max] = max(y_o(1200*length(theta):1700*length(theta))); 98 | I_max = I_max + 1200*length(theta)-1; 99 | if (mod(I_max,length(theta)) == 0) 100 | theta_est_o = theta(length(theta)); 101 | else 102 | theta_est_o = theta(mod(I_max,length(theta))); 103 | end 104 | phi_est_o = phi(floor(I_max/length(theta))+1); 105 | %variance 106 | variance_theta_o = variance_theta_o + (theta_est_o-theta_s)^2; 107 | variance_phi_o = variance_phi_o + (phi_est_o-phi_s)^2; 108 | end 109 | mse_theta_o(q) = variance_theta_o/Q; 110 | mse_phi_o(q) = variance_phi_o/Q; 111 | end 112 | 113 | %array without ambiguity solved 114 | e = ones(1,K); 115 | figure; 116 | plot(snr,10*log10(mse_theta_o)); 117 | hold on; 118 | rho = 10.^(snr/10); 119 | mse_theta_ot= (1+K*rho)./(2*K*(rho.^2)*(4*pi*pi/lambda/lambda)*(cos(theta_s)^2))... 120 | *((sin(phi_s)^2)*d*d*e*(P_o(:,1).^2)+(cos(phi_s)^2)*d*d*e*(P_o(:,2).^2)... 121 | -sin(2*phi_s)*d*d*e*(P_o(:,1).*P_o(:,2)))/(d*d*e*(P_o(:,1).^2)*d*d*e*(P_o(:,2).^2)... 122 | -d*d*e*(P_o(:,1).*P_o(:,2))*d*d*e*(P_o(:,1).*P_o(:,2))); 123 | plot(snr,10*log10(mse_theta_ot),'k--'); 124 | hold on; 125 | plot(snr,10*log10(mse_phi_o),'r'); 126 | hold on; 127 | mse_phi_ot= (1+K*rho)./(2*K*(rho.^2)*(4*pi*pi/lambda/lambda)*(sin(theta_s)^2))... 128 | *((cos(phi_s)^2)*d*d*e*(P_o(:,1).^2)+(sin(phi_s)^2)*d*d*e*(P_o(:,2).^2)... 129 | +sin(2*phi_s)*d*d*e*(P_o(:,1).*P_o(:,2)))/(d*d*e*(P_o(:,1).^2)*d*d*e*(P_o(:,2).^2)... 130 | -d*d*e*(P_o(:,1).*P_o(:,2))*d*d*e*(P_o(:,1).*P_o(:,2))); 131 | plot(snr,10*log10(mse_phi_ot),'c--'); 132 | 133 | 134 | -------------------------------------------------------------------------------- /planar_iso.m: -------------------------------------------------------------------------------- 1 | %optimum isotorpic planar array 2 | clear; 3 | clc; 4 | 5 | N1 = 5; 6 | N2 = 5; 7 | K = 10; 8 | n = -(N1-1)/2:1:(N1-1)/2; 9 | m = [-(N2-1)/2:1:(N2-1)/2]'; 10 | mn = []; 11 | for i = 1:N1 12 | mn = [mn;[n(i)*ones(N2,1),m]]; %mn is the position vector of N*N/2 by 2 dimension 13 | end 14 | lambda = 1; 15 | d = lambda/2; 16 | k0 = 2*pi/lambda; 17 | 18 | %define the array position matrix 19 | dx = d*mn(:,1); 20 | dy = d*mn(:,2); 21 | dxx = dx.*dx; 22 | dyy = dy.*dy; 23 | dxy = dx.*dy; 24 | 25 | %optimum isotropic array with ambiguity 26 | x_o = planar_search_n(dxx,dx,dyy,dy,dxy,K,N1*N2); 27 | P_o = zeros(K,2); 28 | index = 1; 29 | for i = 1:N1*N2 30 | if (abs(x_o(i)-1)<=0.4) 31 | P_o(index,:) = mn(i,:); 32 | index = index + 1; 33 | end 34 | end 35 | % %plot the selected subarray 36 | % spy(fliplr(reshape(x_o,5,5)')); 37 | 38 | %generate the arraival direction 39 | theta_s = 10*pi/180; 40 | phi_s = 175*pi/180; 41 | ux_s = sin(theta_s)*cos(phi_s); 42 | uy_s = sin(theta_s)*sin(phi_s); 43 | vs_o = exp(1i*k0*d*P_o*[ux_s;uy_s]); 44 | %compare beampatterns 45 | theta = 0:0.02:pi/2; 46 | phi = 0:0.02:2*pi; 47 | Y_o = zeros(length(theta),length(phi)); 48 | for i = 1:length(theta) 49 | for k = 1:length(phi) 50 | ux = sin(theta(i))*cos(phi(k)); 51 | uy = sin(theta(i))*sin(phi(k)); 52 | v = exp(1i*k0*d*P_o*[ux;uy]); 53 | Y_o(i,k) = abs(vs_o'*v); 54 | end 55 | end 56 | [X,Y] = meshgrid(phi,theta); 57 | mesh(X,Y,Y_o); 58 | 59 | %calculate the estimation variance 60 | snr = -5:1:30; %signal to noise ratio 61 | T = 1; %the number of snapshots 62 | Q = 500;%Q Monte-Carlo runs 63 | %searching grid points 64 | theta = 0:0.002:pi/2; 65 | phi = 0:0.002:2*pi; 66 | ux = sin(theta')*cos(phi); 67 | uy = sin(theta')*sin(phi); 68 | u_search = [ux(:)';uy(:)']; 69 | 70 | mse_theta_o = zeros(length(snr),1); 71 | mse_phi_o = zeros(length(snr),1); 72 | 73 | for q = 1:length(snr) 74 | variance_theta_o = 0; 75 | variance_phi_o = 0; 76 | for i = 1:Q 77 | %generate the estimated signal 78 | X = (randn(1,T) + 1i * randn(1,T)) / sqrt(2); 79 | Y_o = vs_o * X; 80 | % generate the white noise 81 | sigma_o = 10^(-snr(q)/10) * (norm(Y_o,'fro')^2) / (K * T); 82 | % noise 83 | E_o = sqrt(sigma_o)/sqrt(2)*randn(K,T) + 1i*sqrt(sigma_o)/sqrt(2)*randn(K,T); 84 | %received signal 85 | Y_o = Y_o + E_o; 86 | %DOA estimation 87 | v_o = exp(1i*k0*d*P_o*u_search); 88 | y_o = abs(v_o'*Y_o); 89 | %searching the peak 90 | [y_m1,I_max] = max(y_o); 91 | if (mod(I_max,length(theta)) == 0) 92 | theta_est_o = theta(length(theta)); 93 | else 94 | theta_est_o = theta(mod(I_max,length(theta))); 95 | end 96 | phi_est_o = phi(floor(I_max/length(theta))+1); 97 | %variance 98 | variance_theta_o = variance_theta_o + (theta_est_o-theta_s)^2; 99 | variance_phi_o = variance_phi_o + (phi_est_o-phi_s)^2; 100 | end 101 | mse_theta_o(q) = variance_theta_o/Q; 102 | mse_phi_o(q) = variance_phi_o/Q; 103 | end 104 | 105 | %array without ambiguity solved 106 | e = ones(1,K); 107 | figure; 108 | plot(snr,10*log10(mse_theta_o)); 109 | hold on; 110 | rho = 10.^(snr/10); 111 | mse_theta_ot= (1+K*rho)./(2*K*(rho.^2)*(4*pi*pi/lambda/lambda)*(cos(theta_s)^2)... 112 | *((cos(phi_s)^2)*d*d*e*(P_o(:,1).^2)+(sin(phi_s)^2)*d*d*e*(P_o(:,2).^2))); 113 | plot(snr,10*log10(mse_theta_ot),'k'); 114 | hold on; 115 | plot(snr,10*log10(mse_phi_o),'r'); 116 | hold on; 117 | mse_phi_ot= (1+K*rho)./(2*K*(rho.^2)*(4*pi*pi/lambda/lambda)*(sin(theta_s)^2)... 118 | *((sin(phi_s)^2)*d*d*e*(P_o(:,1).^2)+(cos(phi_s)^2)*d*d*e*(P_o(:,2).^2))); 119 | plot(snr,10*log10(mse_phi_ot),'c'); 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /planar_search_n.m: -------------------------------------------------------------------------------- 1 | function x0 = planar_search_n(dxx,dx,dyy,dy,dxy,K,N) 2 | id = 1:N; 3 | V = nchoosek(id,K); 4 | num = nchoosek(N,K); 5 | e = ones(K,1); 6 | %searching 7 | y = zeros(num,1); 8 | for i = 1:num 9 | if ((e'*dx(V(i,:))==0) && (e'*dy(V(i,:))==0)) 10 | if ((e'*dxy(V(i,:))==0) && (e'*dxx(V(i,:)) == e'*dyy(V(i,:)))) 11 | y(i) = e'*dxx(V(i,:)); 12 | end 13 | end 14 | end 15 | [ymax,Imax] = max(y); 16 | x0 = zeros(N,1); 17 | for i = 1:K 18 | x0(V(Imax,i)) = 1; 19 | end 20 | end 21 | 22 | 23 | 24 | --------------------------------------------------------------------------------