├── cal_weight.m ├── initialise_parameters.m ├── lsmi_method.m ├── main.m ├── mean_cov_based_pro_method.m ├── myplot.m ├── shrinkage_method.m ├── sig_generate.m ├── snr_calculation.m ├── subspace_method.m ├── wcp_method.m └── yus_method.m /cal_weight.m: -------------------------------------------------------------------------------- 1 | function optimal_weight = cal_weight(rec_sig,ps,Rx,method,parameters) % optimal weight's calculation 2 | switch lower(method) 3 | case 'wcp' 4 | optimal_weight = wcp_method(ps,Rx,parameters); 5 | case 'mean_cov_based_pro_method' 6 | optimal_weight = pro_constrained(ps,Rx,parameters); 7 | case 'yus_method' 8 | optimal_weight = yus_method(ps,Rx,parameters); 9 | case 'shrinkage_method' 10 | optimal_weight = shrinkage_method(rec_sig,ps,Rx,parameters); 11 | case 'lsmi_method' 12 | optimal_weight = lsmi(ps,Rx,parameters); 13 | case 'subspace_method' 14 | optimal_weight = subspace_method(Rx,parameters); 15 | end 16 | return; -------------------------------------------------------------------------------- /initialise_parameters.m: -------------------------------------------------------------------------------- 1 | function parameters = initialise_parameters(theta_s,theta1,theta2,Rx,method) % number of elements,covariance matrix 2 | mat_size = size(Rx,1); % covariance matrix size 3 | switch lower(method) 4 | case 'wcp' 5 | Sigma = .3; 6 | wcp_param = Sigma*mat_size; 7 | parameters = struct('sigma',wcp_param); % default wcp parameter 8 | % case 'pro_constrained' 9 | % pro = .95; % default probability constrained parameter 10 | % parameters = struct('probability',pro); 11 | 12 | case 'mean_cov_based_pro_method' 13 | ste_vec_mean = 0 * eye(mat_size); 14 | ste_vec_var = sqrt(.3*(mat_size)/mat_size*eye(mat_size)); 15 | pro = .95; 16 | parameters = struct('probability',pro,'mean',ste_vec_mean,'var',ste_vec_var); 17 | 18 | case 'yus_method' 19 | theta_1_disc_range = theta1-5:.1:theta1+5; % .1 stands for sample gap 20 | theta_2_disc_range = theta2-5:.1:theta2+5; 21 | parameters = struct('range1',theta_1_disc_range,'range2',theta_2_disc_range); 22 | 23 | case 'shrinkage_method' 24 | N = 60; % numbers of snapshot 25 | K = 6; % principle eigenvector 26 | Delta = .1; 27 | rec_sig_angle = [theta_s - 5, theta_s + 5]; 28 | % scan angle outside of received signal region 29 | outside_scan_angle1 = [-90, min(rec_sig_angle)]; 30 | outside_scan_angle2 = [max(rec_sig_angle), 90]; 31 | parameters = struct('snap',N,'principle',K,'delta',Delta,'sig_range',rec_sig_angle,'out_range1',outside_scan_angle1,... 32 | 'out_range2',outside_scan_angle2); 33 | 34 | case 'lsmi_method' 35 | LNR = 10; % default loading noise level-10dB 36 | parameters = struct('lnr',LNR); 37 | 38 | case 'subspace_method' 39 | theta_s_range = theta_s-8:.5:theta_s+8; 40 | theta_1_range = theta1-8:.5:theta1+8; 41 | theta_2_range = theta2-8:.5:theta2+8; 42 | L = 3; % principle eigenvalue 43 | thr = .9; % threhold 44 | parameters = struct('source_range',theta_s_range,'interference1_range',theta_1_range,... 45 | 'interference2_range',theta_2_range,'prin',L,'threshold',thr); 46 | otherwise 47 | error('Method not implemented. Check spelling.'); 48 | end 49 | -------------------------------------------------------------------------------- /lsmi_method.m: -------------------------------------------------------------------------------- 1 | function optimal_weight = lsmi(ps,Rx,parameters) 2 | M = size(Rx,2); 3 | LNR = parameters.lnr; 4 | Loading = LNR * eye(M); 5 | optimal_weight = inv(Rx+Loading)*ps*inv(ps'*(Rx+Loading)*ps); 6 | end 7 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Briskstick/robust-adaptive-beamforming-algorithm/255cf3c74c059a39c41d4ebeadc903f5a7e195d5/main.m -------------------------------------------------------------------------------- /mean_cov_based_pro_method.m: -------------------------------------------------------------------------------- 1 | function optimal_weight = mean_cov_based_pro(ps,Rx,parameters) 2 | 3 | pro = parameters.pro; 4 | mean_val = parameters.ste_vec_mean; % its defalut value equal to zero 5 | var_val = parameters.ste_vec_var; 6 | M = size(Rx,2); 7 | Cov = Rx; 8 | 9 | cvx_begin 10 | variable w(M) complex 11 | minimize norm(sqrtm(Cov)*w) 12 | subject to 13 | norm(var_val*w,2) <= 1/sqrt(-log2(1-pro)) * (real(w'*ps)-1); 14 | cvx_end 15 | optimal_weight = w; 16 | end -------------------------------------------------------------------------------- /myplot.m: -------------------------------------------------------------------------------- 1 | function myplot(Rx,optimal_weight) 2 | M = size(Rx,2); % matrix size 3 | theta = -90:1:90; % scan angle 4 | p = exp(-1j*2*pi*.5*(0:M-1)'*sind(theta)); 5 | y = optimal_weight'*p; 6 | figure; 7 | plot(theta,20*log10(abs(y)/max(abs(y)))); 8 | end -------------------------------------------------------------------------------- /shrinkage_method.m: -------------------------------------------------------------------------------- 1 | function optimal_weight = shrinkage_method(rec_sig,ps,Rx.parameters) 2 | M = size(Rx,2); % size of matrix 3 | v = trace(Rx)/M; 4 | N = parameters.snap; 5 | K = parameters.principle; % principle eigenvector 6 | delta = parameters.Delta; 7 | 8 | xx = rec_sig(:,1:N); 9 | for iter = 1:N 10 | x_norm(iter) = norm(xx(:,iter),2)^4; 11 | end 12 | x_sum = sum(x_norm); 13 | p = 1/N^2 * x_sum - 1/N * norm(Rx,2)^2; 14 | arfa_0 = min(v*p/norm(Rx-v*eye(size(Rx,1)),2)^2, v); 15 | beta_0 = 1 - arfa_0/v; 16 | R_recon = beta_0*Rx + arfa_0*eye(size(Rx,1)); 17 | 18 | % reconstruct covariance matrix 19 | % step1,angle region definition 20 | angle_sector = parameters.rec_sig_angle; 21 | outside_scan_angle1 = parameters.outside_scan_angle1; 22 | outside_scan_angle2 = parameters.outside_scan_angle2; 23 | angle_sector_disc = linspace(min(angle_sector),max(angle_sector),length(angle_sector)); 24 | outside_angle1_disc = linspace(min(outside_scan_angle1),max(outside_scan_angle1),length(outside_scan_angle1)); 25 | outside_angle2_disc = linspace(min(outside_scan_angle2),max(outside_scan_angle2),length(outside_scan_angle2)); 26 | % matrix reconstruction 27 | C_recon_sig = exp(-1j*2*pi*.5*(0:M-1)'*sind(angle_sector_disc))*exp(-1j*2*pi*.5*(0:M-1)'*sind(... 28 | angle_sector_disc)); % default distance/lamda = .5 29 | C_recon_out1 = exp(-1j*2*pi*.5*(0:M-1)'*sind(outside_angle1_disc))*exp(-1j*2*pi*,5*(0:M-1)'*sind(... 30 | outside_angle1_disc)); 31 | C_recon_out2 = exp(-1j*2*pi*.5*(0:M-1)'*sind(outside_angle2_disc))*exp(-1j*2*pi*,5*(0:M-1)'*sind(... 32 | outside_angle2_disc)); 33 | C_recon_out_total = C_recon_out1 + C_recon_out2; 34 | 35 | % % eigen-decomposition 36 | % [U,V] = eig(C_recon_in); 37 | % U_in = U(:,1:K); % principle eigenvector 38 | % P = eye(M) - U_in*U_in'; % projection matrix 39 | 40 | R_inv = inv(R_recon); % inversion of shrinkage matrix 41 | cvx_begin 42 | variable e(M) complex 43 | minimize norm(sqrtm(R_inv)*(ps+e)) 44 | subject to 45 | norm((ps+e),2) < sqrt(M) + delta; % slack constraint 46 | ps'*e == 0 ; 47 | (ps+e)'*P == 0; 48 | norm(sqrtm(C_recon_out_total)*(ps+e)) <= norm(sqrtm(C_recon_out_total)*ps); 49 | cvx_end 50 | ps_recon = ps + e; 51 | optimal_weight = R_inv*ps_recon*(ps_recon'*R_inv*ps_recon); 52 | end 53 | 54 | -------------------------------------------------------------------------------- /sig_generate.m: -------------------------------------------------------------------------------- 1 | function [Rx,Rs,Rn,Ri,ps,rec_sig] = sig_generate(inr1,inr2,snr,snr_noise,theta_s,theta1,theta2,M) 2 | % signal's model: 3 | % x(k) = s(k) + i(k) + n(k) 4 | % = s(k)*a + i(k) + n(k) 5 | % inr1: interference-noise-ratio of interference signal 1 6 | % inr2: interference-noise-ratio of interference signal 2 7 | % snr: signal-noise-ratio of target signal 8 | % snr_noise: noise power 9 | % theta_s: target signal's DOA 10 | % theta1: interference signal1's DOA 11 | % theta2: interference signal2's DOA 12 | % M: number of elements 13 | 14 | % default parameters: 15 | % f_s:sample frequency 16 | % f:signal's frequency 17 | % T:duration of signal 18 | % c:sound's velocity 19 | % N:snapshot's number 20 | % d:gap between element 21 | f_s = 5000; % sample frequency 22 | f = 1000; % signal frequency 23 | N = 60; % snapshot 24 | T = .05; t = 1/f_s:1/f_s:T; 25 | c = 340; 26 | lamda = c/f; 27 | d = .5*lamda; % default gap between element 28 | 29 | % steering vector formulation 30 | ps = exp(-1j*2*pi*d*sind(theta_s)*(0:M-1)'/lamda); 31 | p1 = exp(-1j*2*pi*d*sind(theta1)*(0:M-1)'/lamda); 32 | p2 = exp(-1j*2*pi*d*sind(theta2)*(0:M-1)'/lamda); 33 | 34 | % signal generation 35 | tar_sig = wgn(1,length(t), snr+snr_noise); 36 | inf1 = wgn(1,length(t),inr1+snr_noise); % interference signal 1 37 | inf2 = wgn(1,length(t),inr2+snr_noise); % interference signal 2 38 | noise = wgn(M,length(t),snr_noise); 39 | 40 | rec_sig = ps*tar_sig + p1*inf1 + p2*inf2 + noise; % received signal 41 | interference = p1*inf1 + p2*inf2; 42 | sig = ps * tar_sig; 43 | 44 | % snapshot estimation of covariance matrix 45 | Rx = rec_sig(:,1:N)*rec_sig(:,1:N)'/N; % total received signal covariance 46 | Rs = sig(:,1:N)*sig(:,1:N)'/N; % signal covariance 47 | Ri = interference(:,1:N)*interference(:,1:N)'/N; % interference covariance 48 | Rn = noise(:,1:N)*noise(:,1:N)'/N; % noise covariance 49 | end 50 | 51 | 52 | -------------------------------------------------------------------------------- /snr_calculation.m: -------------------------------------------------------------------------------- 1 | function snr_output = snr_calculation(Rs,Ri,Rn,w_opt) 2 | R_in = Rn + Ri; 3 | snr_output = 10*log10(abs(w_opt'*Rs*w_opt*inv(w_opt'*R_in*w_opt))); 4 | fprintf('snr_output = %f\n', snr_output); 5 | end -------------------------------------------------------------------------------- /subspace_method.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Briskstick/robust-adaptive-beamforming-algorithm/255cf3c74c059a39c41d4ebeadc903f5a7e195d5/subspace_method.m -------------------------------------------------------------------------------- /wcp_method.m: -------------------------------------------------------------------------------- 1 | function w = wcp_method(ps,Rx,parameters) 2 | sigma = parameters.sigma; % default algo parameter 3 | 4 | Cov = Rx; % covariance matrix of received signal 5 | % algo formulation 6 | M = size(Rx,2); 7 | cvx_begin 8 | variable w(M) complex; 9 | minimize norm(sqrtm(Cov)*w) 10 | subject to 11 | sigma * norm(w,2) <= real(w'*ps) - 1; 12 | imag(w'*ps) == 0; 13 | cvx_end 14 | optimal_weight = w; 15 | end 16 | -------------------------------------------------------------------------------- /yus_method.m: -------------------------------------------------------------------------------- 1 | function optimal_weight = yus_method(ps,Rx,parameters) 2 | M = size(Rx,2); % matrix size 3 | theta_range1 = parameters.range1; 4 | theta_range2 = parameters.range2; 5 | 6 | C1 = zeros(M,M); 7 | for iter1 = 1:length(theta_range1) 8 | a1 = exp(-1j*2*pi*.5*sind(theta_range1(iter1))*(0:M-1)'); % default distance/lamda ratio is .5 9 | C1 = C1 + inv(a1'*inv(Rx)*a1)*a1*a1'; 10 | end 11 | 12 | C2 = zeros(M,M); 13 | for iter2 = 1:length(theta_range1) 14 | a2 = exp(-1j*2*pi*.5*sind(theta_range2(iter2))*(0:M-1)'); % default distance/lamda ratio is .5 15 | C2 = C2 + inv(a2'*inv(Rx)*a2)*a2*a2'; 16 | end 17 | 18 | C_recon = C1 + C2; % Capon estimated covariance matrix 19 | R_inv = inv(C_recon); 20 | 21 | cvx_begin 22 | variable e(M) complex 23 | minimize norm(sqrtm(R_inv)*(ps+e)) 24 | subject to 25 | ps' * e == 0; 26 | norm(sqrtm(C_recon)*(ps+e)) <= norm(sqrtm(C_recon)*ps); 27 | cvx_end 28 | ps_recon = ps + e; 29 | optimal_weight = R_inv*ps_recon*inv(ps_recon'*R_inv*ps_recon); 30 | end 31 | 32 | 33 | 34 | --------------------------------------------------------------------------------