├── Fig12a.jpg ├── Fig12b.jpg ├── Fig7c.jpg ├── README.md ├── RIS array ├── ArrayGenerate.m ├── CalculateCC.m ├── CalculateReflect.m ├── CalculateScatter.m ├── ChangeGrid.m ├── ControlRIS_BGA.m ├── ControlRIS_BGApolar.m ├── ControlRIS_DPSbeam.m ├── ControlRIS_Perfectbeam.m ├── GetCC_LOS.m ├── GetCC_RIS.m ├── LinearInterpolate.m ├── LinearInterpolateGrid.m ├── LoadParameter.m ├── Main_RISarray_WithRotation.m ├── Main_RISarray_WithoutRotation.m ├── Pattern │ ├── AntH2.xlsx │ ├── AntH3.xlsx │ ├── AntH4.xlsx │ ├── AntV2.xlsx │ ├── AntV3.xlsx │ └── AntV4.xlsx ├── RodriguesRotVec.m └── RotateAntenna.m └── RIS element ├── CalculateCC.m ├── CalculateReflect.m ├── CalculateScatter.m ├── ChangeGrid.m ├── LinearInterpolate.m ├── LoadParameter.m ├── Main.m ├── Pattern ├── AntH2.xlsx ├── AntH3.xlsx ├── AntH4.xlsx ├── AntV2.xlsx ├── AntV3.xlsx └── AntV4.xlsx └── RotateAntenna.m /Fig12a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/Fig12a.jpg -------------------------------------------------------------------------------- /Fig12b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/Fig12b.jpg -------------------------------------------------------------------------------- /Fig7c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/Fig7c.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Matlab code for "A Novel Channel Model for Reconfigurable Intelligent Surfaces with Consideration of Polarization and Switch Impairments" 2 | (c) 2023 De-Ming Chian and Chao-Kai Wen e-mail: icefreeman123@gmail.com and chaokai.wen@mail.nsysu.edu.tw 3 | 4 | ## Introduction 5 | This repository contains the channel model for Reconfigurable Intelligent Surfaces (RIS) described in 6 | De-Ming Chian, Chao-Kai Wen, Chi-Hung Wu, Fu-Kang Wang, and Kai-Kit Wong, “A novel channel model for reconfigurable intelligent surfaces with consideration of polarization and switch impairments,” arXiv preprint arXiv:2304.03713, 2023. [Online]. Available: https://arxiv.org/abs/2304.03713. 7 | 8 | The final version is published in D.-M. Chian, C.-K. Wen, C.-H. Wu, F.-K. Wang and K.-K. Wong, "A Novel Channel Model for Reconfigurable Intelligent Surfaces With Consideration of Polarization and Switch Impairments," IEEE Transactions on Antennas and Propagation, vol. 72, no. 4, pp. 3680-3695, April 2024. Available: https://ieeexplore.ieee.org/document/10462906. 9 | 10 | ## Requirements 11 | - Matlab (R2022b) 12 | 13 | ## Hint 14 | - If this code is applied in different cases, the transformation of polarization for the scattered and reflected waves and their tuning coefficients must be redefined. They are described in equations [22] and [23] of our article. 15 | 16 | ## File 1: RIS element (Consideration of polarization and switch impairments) 17 | 18 | ### Step1. Download the main script, functions, and data 19 | - Main script: Main.m 20 | - Functions: CalculateCC.m / CalculateReflect.m / CalculateScatter.m /
21 |        ChangeGrid.m / LinearInterpolate.m /
22 |        LoadParameter.m / RotateAntenna.m
23 | - Data: Pattern file (AntH2.xlsx / AntH3.xlsx / AntH4.xlsx /
24 |           AntV2.xlsx / AntV3.xlsx / AntV4.xlsx)
25 | 26 | ### Step2. Run the main script 27 | 28 | ### Results 29 | The following results are reproduced from Fig. 7(c) of our paper:
30 | ![Image text](https://github.com/icefreeman123/Matlab_RIS_ChannelModel/blob/main/Fig7c.jpg) 31 | 32 | ## File 2: RIS array (Controlling algorithm) 33 | 34 | ### Step1. Download the main scripts, functions, and data 35 | - Main script 1: Main_RISarray_WithoutRotation.m 36 | - Main script 2: Main_RISarray_WithRotation.m 37 | - Functions: CalculateCC.m / CalculateReflect.m / CalculateScatter.m /
38 |        ChangeGrid.m / LinearInterpolate.m / LinearInterpolateGrid.m /
39 |        LoadParameter.m / ArrayGenerate.m /
40 |        RodriguesRotVec.m / RotateAntenna.m /
41 |        ControlRIS_Perfectbeam.m / ControlRIS_DPSbeam.m /
42 |        ControlRIS_BGA.m / ControlRIS_BGApolar.m /
43 |        GetCC_LOS.m / GetCC_RIS.m
44 | - Data: Pattern file (AntH2.xlsx / AntH3.xlsx / AntH4.xlsx /
45 |           AntV2.xlsx / AntV3.xlsx / AntV4.xlsx)
46 | 47 | ### Step2. Run the main script 1 and 2, corresponding to Fig. 12(a) and (b), respectively. The results with one of controlling algorithms will be obtained. 48 | (Please choose the controlling algorithm in the 43-th line. Ex.: AntData.CtlMethod = 'Perfect_beam'; is based on perfect beamforming.) 49 | 50 | ### Results 51 | The following results are reproduced from Fig. 12(a) of our paper:
52 | ![Image text](https://github.com/icefreeman123/Matlab_RIS_ChannelModel/blob/main/Fig12a.jpg) 53 | 54 | The following results are reproduced from Fig. 12(b) of our paper:
55 | ![Image text](https://github.com/icefreeman123/Matlab_RIS_ChannelModel/blob/main/Fig12b.jpg) 56 | -------------------------------------------------------------------------------- /RIS array/ArrayGenerate.m: -------------------------------------------------------------------------------- 1 | function [ AntDataFold ] = ArrayGenerate( AntData, AntDataFold ) 2 | %% Setup 3 | V = AntDataFold.V; 4 | H = AntDataFold.H; 5 | T = AntDataFold.T; 6 | Array_a = AntDataFold.size(1); % Array size (Vertical direction) 7 | Array_b = AntDataFold.size(2); % Array size (Horizontal direction) 8 | no_ant = Array_a * Array_b; 9 | 10 | ArrayCenterLoc = AntDataFold.position{1}; % Array center. Unit: m. 11 | ArrayCenterNorVect = AntDataFold.normal; % Normal vector of array 12 | freq = AntData.freq; 13 | speed = physconst('lightspeed'); % speed of light(unit: m/s) 14 | lambda = speed/freq; % wavelength(unit: Hz) 15 | AntDist = lambda/2; % Distance between two antennas in the array. 16 | 17 | %% Duplicate pattern 18 | V_cell = cell(Array_a, Array_b); 19 | [V_cell{:}] = deal(cell2mat(V)); 20 | H_cell = cell(Array_a, Array_b); 21 | [H_cell{:}] = deal(cell2mat(H)); 22 | T_cell = cell(Array_a, Array_b); 23 | [T_cell{:}] = deal(cell2mat(T)); 24 | 25 | %% Duplicate location 26 | % Original antenna location (default) 27 | AllPt = zeros(no_ant, 3); 28 | GridPt_a = AntDist * (0:(Array_a-1)); 29 | GridPt_b = AntDist * (0:(Array_b-1)); 30 | AllPt(:,3) = repmat(GridPt_a.', [Array_b,1]); 31 | AllPt(:,2) = reshape(repmat(GridPt_b, [Array_a,1]), [],1); 32 | AllPt_cell = mat2cell(AllPt, ones(no_ant,1), 3); 33 | AllPt_cell = reshape(AllPt_cell, Array_a, Array_b); % default 34 | AllPtCenter = [0, (AntDist*(Array_b-1)/2), (AntDist*(Array_a-1)/2)]; % default 35 | AllPtAndCenter = [AllPt ; AllPtCenter].'; 36 | 37 | % Calculate rotation vector (based on Rodrigues' rotation formula) 38 | NorVec_org = [1;0;0]; % default 39 | AllPtAndCenter_new = RodriguesRotVec( NorVec_org, ArrayCenterNorVect, AllPtAndCenter ); 40 | 41 | % Move center 42 | MoveDist = ArrayCenterLoc - AllPtAndCenter_new(:,end); 43 | AllPtAndCenter_new2 = AllPtAndCenter_new + repmat(MoveDist, 1,size(AllPtAndCenter_new,2)); 44 | %%%%% Check: ArrayCenterLoc = AllPtAndCenter_new2(:,end); 45 | AllPt_new = AllPtAndCenter_new2(:, 1:end-1); 46 | AllPt_new_cell = mat2cell(AllPt_new, 3, ones(no_ant,1)); 47 | AllPt_new_cell = reshape(AllPt_new_cell, Array_a, Array_b); 48 | 49 | %% Output 50 | AntDataFold.V = V_cell; 51 | AntDataFold.H = H_cell; 52 | AntDataFold.T = T_cell; 53 | AntDataFold.position = AllPt_new_cell; 54 | AntDataFold.no_ant = no_ant; 55 | 56 | end 57 | 58 | -------------------------------------------------------------------------------- /RIS array/CalculateCC.m: -------------------------------------------------------------------------------- 1 | function [ Coeff_mat ] = CalculateCC( AntData, tx, rx ) 2 | %% Setup 3 | freq = AntData.freq; 4 | LossType = AntData.LossType; 5 | speed = physconst('lightspeed'); % speed of light(unit: m/s) 6 | lambda = speed/freq; % wavelength(unit: Hz) 7 | k = (2*pi)/lambda; % Wave number 8 | 9 | tx_position = tx.position; % Each antenna location. 10 | rx_position = rx.position; % Each antenna location. 11 | tx_V = tx.V; 12 | tx_H = tx.H; 13 | rx_V = rx.V; 14 | rx_H = rx.H; 15 | no_ant_tx = tx.no_ant; 16 | no_ant_rx = rx.no_ant; 17 | 18 | %% Amplitude 19 | tx_position_tmp = tx_position(:); 20 | rx_position_tmp = rx_position(:); 21 | tx_Vtmp = tx_V(:); 22 | tx_Htmp = tx_H(:); 23 | rx_Vtmp = rx_V(:); 24 | rx_Htmp = rx_H(:); 25 | V_final_mat = zeros(no_ant_rx, no_ant_tx); 26 | H_final_mat = zeros(no_ant_rx, no_ant_tx); 27 | Amp_mat = zeros(no_ant_rx, no_ant_tx); 28 | for i = 1:no_ant_tx 29 | tx_position_tmp2 = tx_position_tmp{i}; 30 | tx_Vtmp2 = tx_Vtmp{i}; 31 | tx_Htmp2 = tx_Htmp{i}; 32 | for j = 1:no_ant_rx 33 | rx_position_tmp2 = rx_position_tmp{j}; 34 | rx_Vtmp2 = rx_Vtmp{j}; 35 | rx_Htmp2 = rx_Htmp{j}; 36 | % 37 | [AOD, AOA] = CalculateAngle( tx_position_tmp2, rx_position_tmp2 ); % Angles between Tx and Rx 38 | aod_r = AOD(2).'*pi/180; 39 | aoa_r = AOA(2).'*pi/180; 40 | eod_r = AOD(1).'*pi/180; 41 | eoa_r = AOA(1).'*pi/180; 42 | % 43 | [ Vt, Ht ] = LinearInterpolate( tx_Vtmp2, tx_Htmp2, tx , aod_r , eod_r ); 44 | [ Vr, Hr ] = LinearInterpolate( rx_Vtmp2, rx_Htmp2, rx , aoa_r , eoa_r ); 45 | V_final = Vr *Vt; 46 | H_final = Hr *Ht; 47 | Amp = V_final - H_final; 48 | % 49 | V_final_mat(j, i) = V_final; 50 | H_final_mat(j, i) = H_final; 51 | Amp_mat(j, i) = Amp; 52 | end 53 | end 54 | 55 | %% Phase 56 | Phase_mat = zeros(no_ant_rx, no_ant_tx); 57 | for i = 1:no_ant_tx 58 | tx_position_tmp2 = tx_position_tmp{i}; 59 | for j = 1:no_ant_rx 60 | rx_position_tmp2 = rx_position_tmp{j}; 61 | r_s = rx_position_tmp2 - tx_position_tmp2; 62 | norm_r_s = sqrt( sum( r_s.^2 ,1 ) ); 63 | Phase = k * mod(norm_r_s, lambda); 64 | Phase_mat(j, i) = Phase; 65 | end 66 | end 67 | 68 | %% Path Loss 69 | switch LossType 70 | case 'withloss' 71 | loss_dB_mat = zeros(no_ant_rx, no_ant_tx); 72 | for i = 1:no_ant_tx 73 | tx_position_tmp2 = tx_position_tmp{i}; 74 | for j = 1:no_ant_rx 75 | rx_position_tmp2 = rx_position_tmp{j}; 76 | loss_dB = pathloss( tx_position_tmp2, rx_position_tmp2, lambda ); 77 | loss_dB_mat(j, i) = loss_dB; 78 | end 79 | end 80 | case 'noloss' % otherwise 81 | loss_dB_mat = zeros(no_ant_rx, no_ant_tx); 82 | end 83 | loss_mat = sqrt( 10.^( 0.1 * -1 * loss_dB_mat ) ); 84 | %% Calculate Coeff. 85 | Coeff_mat = loss_mat .* Amp_mat .* exp(-1j*Phase_mat); 86 | end 87 | %% Pathloss 88 | function [ loss ] = pathloss( tx_position, rx_position, lambda ) 89 | txpos = tx_position; 90 | rxpos = rx_position; 91 | d_3d = sqrt(sum( (rxpos-txpos).^2 )); 92 | loss = 20 * log10(4*pi*d_3d / lambda); 93 | end 94 | %% Angle 95 | function [ AOD, AOA ] = CalculateAngle( T_position, R_position ) 96 | % Vector in Cart. coordinate 97 | X_vec = R_position(1) - T_position(1); 98 | Y_vec = R_position(2) - T_position(2); 99 | Z_vec = R_position(3) - T_position(3); 100 | 101 | angles = zeros( 4, 1 ); 102 | % AOD-Horizontal polarization 103 | angles(1,1) = atan2( Y_vec, X_vec ); % [–pi, pi] 104 | angles(1, isnan(angles(1,1)) ) = 0; 105 | % AOD-Vertical polarization 106 | angles(3,1) = atan2( Z_vec, sqrt(X_vec.^2 + Y_vec.^2) ); % [–pi, pi] 107 | angles(3, isnan(angles(3,1)) ) = 0; 108 | % AOA-Horizontal polarization 109 | angles(2,1) = pi + angles(1,1); 110 | % AOA-Vertical polarization 111 | angles(4,1) = -1 * angles(3,1); 112 | 113 | % Change to (0,360) deg. 114 | angles = angles * 180/pi; 115 | angles(1,1) = mod( angles(1,1) , 360); 116 | angles(2,1) = mod( angles(2,1) , 360); 117 | 118 | % AOD (1. V / 2. H) 119 | AOD(1,1) = angles(3,1); 120 | AOD(2,1) = angles(1,1); 121 | % AOA (1. V / 2. H) 122 | AOA(1,1) = angles(4,1); 123 | AOA(2,1) = angles(2,1); 124 | 125 | % Vertical polarization changes to (0,180) deg. 126 | AOD(1,1) = -1*AOD(1,1) + 90; 127 | AOA(1,1) = -1*AOA(1,1) + 90; 128 | % Horizontal polarization changes to (0,360) deg. 129 | AODtmp = AOD(2,1); 130 | AODtmp_idx = AODtmp < 0; 131 | AODtmp(AODtmp_idx) = AODtmp(AODtmp_idx) + 360; 132 | AOD(2,1) = AODtmp; 133 | AOAtmp = AOA(2,1); 134 | AOAtmp_idx = AOAtmp < 0; 135 | AOAtmp(AOAtmp_idx) = AOAtmp(AOAtmp_idx) + 360; 136 | AOA(2,1) = AOAtmp; 137 | end 138 | 139 | -------------------------------------------------------------------------------- /RIS array/CalculateReflect.m: -------------------------------------------------------------------------------- 1 | function [ Coeff_mat ] = CalculateReflect( AntData, RISLoc ) 2 | %% Setup 3 | freq = AntData.freq; 4 | LossType = AntData.LossType; 5 | speed = physconst('lightspeed'); % speed of light(unit: m/s) 6 | lambda = speed/freq; % wavelength(unit: Hz) 7 | k = (2*pi)/lambda; % Wave number 8 | 9 | tx = AntData.tx; 10 | ris = AntData.ris; 11 | rx = AntData.rx; 12 | tx_position = tx.position; % Each antenna location. 13 | ris_position = RISLoc; % Array center. 14 | rx_position = rx.position; % Each antenna location. 15 | tx_V = tx.V; 16 | tx_H = tx.H; 17 | rx_V = rx.V; 18 | rx_H = rx.H; 19 | no_ant_tx = tx.no_ant; 20 | no_ant_rx = rx.no_ant; 21 | 22 | %% Amplitude 23 | tx_position_tmp = tx_position(:); 24 | rx_position_tmp = rx_position(:); 25 | tx_Vtmp = tx_V(:); 26 | tx_Htmp = tx_H(:); 27 | rx_Vtmp = rx_V(:); 28 | rx_Htmp = rx_H(:); 29 | V_Tx2RIS_mat = zeros(1, no_ant_tx); 30 | H_Tx2RIS_mat = zeros(1, no_ant_tx); 31 | V_RIS2Rx_mat = zeros(1, no_ant_rx); 32 | H_RIS2Rx_mat = zeros(1, no_ant_rx); 33 | aoa_r_Tx2RIS_mat = zeros(1, no_ant_tx); 34 | eoa_r_Tx2RIS_mat = zeros(1, no_ant_tx); 35 | aod_r_RIS2Rx_mat = zeros(1, no_ant_rx); 36 | eod_r_RIS2Rx_mat = zeros(1, no_ant_rx); 37 | S_matrix_cell = cell(no_ant_rx, no_ant_tx); 38 | Amp_mat = zeros(no_ant_rx, no_ant_tx); 39 | % Tx2RIS 40 | for i = 1:no_ant_tx 41 | tx_position_tmp2 = tx_position_tmp{i}; 42 | tx_Vtmp2 = tx_Vtmp{i}; 43 | tx_Htmp2 = tx_Htmp{i}; 44 | % Angle of Tx2RIS 45 | [AOD_Tx2RIS, AOA_Tx2RIS] = CalculateAngle( tx_position_tmp2, ris_position ); % Angles between Tx and Rx 46 | aod_r_Tx2RIS = AOD_Tx2RIS(2).'*pi/180; 47 | aoa_r_Tx2RIS = AOA_Tx2RIS(2).'*pi/180; % phi_i 48 | eod_r_Tx2RIS = AOD_Tx2RIS(1).'*pi/180; 49 | eoa_r_Tx2RIS = AOA_Tx2RIS(1).'*pi/180; % theta_i 50 | aoa_r_Tx2RIS_mat(1, i) = aoa_r_Tx2RIS; 51 | eoa_r_Tx2RIS_mat(1, i) = eoa_r_Tx2RIS; 52 | % Signal of Tx2RIS 53 | [ Vt, Ht ] = LinearInterpolate( tx_Vtmp2, tx_Htmp2, tx , aod_r_Tx2RIS , eod_r_Tx2RIS ); 54 | V_Tx2RIS = 1 *Vt; 55 | H_Tx2RIS = 1 *Ht; 56 | V_Tx2RIS_mat(1, i) = V_Tx2RIS; 57 | H_Tx2RIS_mat(1, i) = H_Tx2RIS; 58 | end 59 | % RIS2Rx 60 | for j = 1:no_ant_rx 61 | rx_position_tmp2 = rx_position_tmp{j}; 62 | rx_Vtmp2 = rx_Vtmp{j}; 63 | rx_Htmp2 = rx_Htmp{j}; 64 | % Angle of RIS2Rx 65 | [AOD_RIS2Rx, AOA_RIS2Rx] = CalculateAngle( ris_position, rx_position_tmp2 ); % Angles between RIS and Rx 66 | aod_r_RIS2Rx = AOD_RIS2Rx(2).'*pi/180; % phi_s 67 | aoa_r_RIS2Rx = AOA_RIS2Rx(2).'*pi/180; 68 | eod_r_RIS2Rx = AOD_RIS2Rx(1).'*pi/180; % theta_s 69 | eoa_r_RIS2Rx = AOA_RIS2Rx(1).'*pi/180; 70 | aod_r_RIS2Rx_mat(1, j) = aod_r_RIS2Rx; 71 | eod_r_RIS2Rx_mat(1, j) = eod_r_RIS2Rx; 72 | % Signal of RIS2Rx 73 | [ Vr, Hr ] = LinearInterpolate( rx_Vtmp2, rx_Htmp2, rx , aoa_r_RIS2Rx , eoa_r_RIS2Rx ); 74 | V_RIS2Rx = Vr *1; 75 | H_RIS2Rx = Hr *1; 76 | V_RIS2Rx_mat(1, j) = V_RIS2Rx; 77 | H_RIS2Rx_mat(1, j) = H_RIS2Rx; 78 | end 79 | 80 | % Reflection Matrix (Good conductor) 81 | R_V = -1; 82 | R_H = 1; 83 | 84 | % Reflection coefficient 85 | NorVec = AntData.ris.normal; % Normal vector of RIS 86 | Amp_mat = zeros(no_ant_rx, no_ant_tx); 87 | for i = 1:no_ant_tx 88 | tx_position_tmp2 = tx_position_tmp{i}; 89 | for j = 1:no_ant_rx 90 | rx_position_tmp2 = rx_position_tmp{j}; 91 | % Vector 92 | Vec_RIS2Tx = (tx_position_tmp2-ris_position)/norm(tx_position_tmp2-ris_position); 93 | Vec_RIS2Rx = (rx_position_tmp2-ris_position)/norm(rx_position_tmp2-ris_position); 94 | Vec_Combine = (Vec_RIS2Tx+Vec_RIS2Rx)/norm(Vec_RIS2Tx+Vec_RIS2Rx); 95 | % Reflection coefficient 96 | %%% Method 1: Tunung RefEff 97 | Amp = V_RIS2Rx * (R_V*V_Tx2RIS - 0) - H_RIS2Rx * (0 - R_H*H_Tx2RIS); 98 | %%% Method 2: According to the reflection angle 99 | % if isequal(sum(abs(NorVec-Vec_Combine)), 0) % Incident Angle = Reflection Angle 100 | % Amp = V_RIS2Rx * (R_V*V_Tx2RIS - 0) - H_RIS2Rx * (0 - R_H*H_Tx2RIS); 101 | % else % Incident Angle ~= Reflection Angle 102 | % Amp = 0; 103 | % % It could not correct in the practical environment because 104 | % % the reflected signal exists besides the reflection angle. 105 | % end 106 | % 107 | Amp_mat(j, i) = Amp; 108 | end 109 | end 110 | 111 | %% Phase 112 | tx_position_tmp = tx_position(:); 113 | rx_position_tmp = rx_position(:); 114 | Phase_mat = zeros(no_ant_rx, no_ant_tx); 115 | for i = 1:no_ant_tx 116 | tx_position_tmp2 = tx_position_tmp{i}; % i-th Tx location 117 | vec_Tx2RIS = ris_position - tx_position_tmp2; 118 | len_Tx2RIS = sqrt( sum( vec_Tx2RIS.^2 ,1 ) ); 119 | for j = 1:no_ant_rx 120 | rx_position_tmp2 = rx_position_tmp{j}; % j-th Rx location 121 | vec_RIS2Rx = rx_position_tmp2 - ris_position; 122 | len_RIS2Rx = sqrt( sum( vec_RIS2Rx.^2 ,1 ) ); 123 | len_total = len_Tx2RIS + len_RIS2Rx; 124 | Phase = k * mod(len_total, lambda); 125 | Phase_mat(j, i) = Phase; 126 | end 127 | end 128 | 129 | %% Path Loss 130 | switch LossType 131 | case 'withloss' 132 | loss_dB_Tx2RIS_mat = zeros(no_ant_rx, no_ant_tx); 133 | loss_dB_RIS2Rx_mat = zeros(no_ant_rx, no_ant_tx); 134 | for i = 1:no_ant_tx 135 | tx_position_tmp2 = tx_position_tmp{i}; 136 | for j = 1:no_ant_rx 137 | rx_position_tmp2 = rx_position_tmp{j}; 138 | loss_dB_Tx2RIS = pathloss( tx_position_tmp2, ris_position, lambda ); 139 | loss_dB_RIS2Rx = pathloss( ris_position, rx_position_tmp2, lambda ); 140 | loss_dB_Tx2RIS_mat(j, i) = loss_dB_Tx2RIS; 141 | loss_dB_RIS2Rx_mat(j, i) = loss_dB_RIS2Rx; 142 | end 143 | end 144 | case 'noloss' % otherwise 145 | loss_dB_Tx2RIS_mat = zeros(no_ant_rx, no_ant_tx); 146 | loss_dB_RIS2Rx_mat = zeros(no_ant_rx, no_ant_tx); 147 | end 148 | loss_mat = (sqrt(10.^(0.1*-1*loss_dB_Tx2RIS_mat))) .* (sqrt(10.^(0.1*-1*loss_dB_RIS2Rx_mat))); 149 | 150 | %% Calculate Coeff. 151 | Coeff_mat = loss_mat .* Amp_mat .* exp(-1j*Phase_mat); 152 | 153 | end 154 | %% Pathloss 155 | function [ loss ] = pathloss( tx_position, rx_position, lambda ) 156 | txpos = tx_position; 157 | rxpos = rx_position; 158 | d_3d = sqrt(sum( (rxpos-txpos).^2 )); 159 | loss = 20 * log10(4*pi*d_3d / lambda); 160 | end 161 | %% Angle 162 | function [ AOD, AOA ] = CalculateAngle( T_position, R_position ) 163 | % Vector in Cart. coordinate 164 | X_vec = R_position(1) - T_position(1); 165 | Y_vec = R_position(2) - T_position(2); 166 | Z_vec = R_position(3) - T_position(3); 167 | 168 | angles = zeros( 4, 1 ); 169 | % AOD-Horizontal polarization 170 | angles(1,1) = atan2( Y_vec, X_vec ); % [–pi, pi] 171 | angles(1, isnan(angles(1,1)) ) = 0; 172 | % AOD-Vertical polarization 173 | angles(3,1) = atan2( Z_vec, sqrt(X_vec.^2 + Y_vec.^2) ); % [–pi, pi] 174 | angles(3, isnan(angles(3,1)) ) = 0; 175 | % AOA-Horizontal polarization 176 | angles(2,1) = pi + angles(1,1); 177 | % AOA-Vertical polarization 178 | angles(4,1) = -1 * angles(3,1); 179 | 180 | % Change to (0,360) deg. 181 | angles = angles * 180/pi; 182 | angles(1,1) = mod( angles(1,1) , 360); 183 | angles(2,1) = mod( angles(2,1) , 360); 184 | 185 | % AOD (1. V / 2. H) 186 | AOD(1,1) = angles(3,1); 187 | AOD(2,1) = angles(1,1); 188 | % AOA (1. V / 2. H) 189 | AOA(1,1) = angles(4,1); 190 | AOA(2,1) = angles(2,1); 191 | 192 | % Vertical polarization changes to (0,180) deg. 193 | AOD(1,1) = -1*AOD(1,1) + 90; 194 | AOA(1,1) = -1*AOA(1,1) + 90; 195 | % Horizontal polarization changes to (0,360) deg. 196 | AODtmp = AOD(2,1); 197 | AODtmp_idx = AODtmp < 0; 198 | AODtmp(AODtmp_idx) = AODtmp(AODtmp_idx) + 360; 199 | AOD(2,1) = AODtmp; 200 | AOAtmp = AOA(2,1); 201 | AOAtmp_idx = AOAtmp < 0; 202 | AOAtmp(AOAtmp_idx) = AOAtmp(AOAtmp_idx) + 360; 203 | AOA(2,1) = AOAtmp; 204 | end 205 | -------------------------------------------------------------------------------- /RIS array/CalculateScatter.m: -------------------------------------------------------------------------------- 1 | function [ Coeff_mat ] = CalculateScatter( AntData, RISLoc ) 2 | %% Setup 3 | freq = AntData.freq; 4 | LossType = AntData.LossType; 5 | speed = physconst('lightspeed'); % speed of light(unit: m/s) 6 | lambda = speed/freq; % wavelength(unit: Hz) 7 | k = (2*pi)/lambda; % Wave number 8 | 9 | tx = AntData.tx; 10 | ris = AntData.ris; 11 | rx = AntData.rx; 12 | tx_position = tx.position; % Each antenna location. 13 | ris_position = RISLoc; % Array center. 14 | rx_position = rx.position; % Each antenna location. 15 | tx_V = tx.V; 16 | tx_H = tx.H; 17 | rx_V = rx.V; 18 | rx_H = rx.H; 19 | no_ant_tx = tx.no_ant; 20 | no_ant_rx = rx.no_ant; 21 | 22 | size_ris = ris.size; 23 | a = AntData.ris.area_a; 24 | b = AntData.ris.area_b; 25 | a_all = a * size_ris(1,1); 26 | b_all = b * size_ris(1,2); 27 | 28 | %% Amplitude 29 | tx_position_tmp = tx_position(:); 30 | rx_position_tmp = rx_position(:); 31 | tx_Vtmp = tx_V(:); 32 | tx_Htmp = tx_H(:); 33 | rx_Vtmp = rx_V(:); 34 | rx_Htmp = rx_H(:); 35 | V_Tx2RIS_mat = zeros(1, no_ant_tx); 36 | H_Tx2RIS_mat = zeros(1, no_ant_tx); 37 | V_RIS2Rx_mat = zeros(1, no_ant_rx); 38 | H_RIS2Rx_mat = zeros(1, no_ant_rx); 39 | aoa_r_Tx2RIS_mat = zeros(1, no_ant_tx); 40 | eoa_r_Tx2RIS_mat = zeros(1, no_ant_tx); 41 | aod_r_RIS2Rx_mat = zeros(1, no_ant_rx); 42 | eod_r_RIS2Rx_mat = zeros(1, no_ant_rx); 43 | S_matrix_cell = cell(no_ant_rx, no_ant_tx); 44 | Amp_mat = zeros(no_ant_rx, no_ant_tx); 45 | % Tx2RIS 46 | for i = 1:no_ant_tx 47 | tx_position_tmp2 = tx_position_tmp{i}; 48 | tx_Vtmp2 = tx_Vtmp{i}; 49 | tx_Htmp2 = tx_Htmp{i}; 50 | % Angle of Tx2RIS 51 | [AOD_Tx2RIS, AOA_Tx2RIS] = CalculateAngle( tx_position_tmp2, ris_position ); % Angles between Tx and Rx 52 | aod_r_Tx2RIS = AOD_Tx2RIS(2).'*pi/180; 53 | aoa_r_Tx2RIS = AOA_Tx2RIS(2).'*pi/180; % phi_i 54 | eod_r_Tx2RIS = AOD_Tx2RIS(1).'*pi/180; 55 | eoa_r_Tx2RIS = AOA_Tx2RIS(1).'*pi/180; % theta_i 56 | aoa_r_Tx2RIS_mat(1, i) = aoa_r_Tx2RIS; 57 | eoa_r_Tx2RIS_mat(1, i) = eoa_r_Tx2RIS; 58 | % Signal of Tx2RIS 59 | [ Vt, Ht ] = LinearInterpolate( tx_Vtmp2, tx_Htmp2, tx , aod_r_Tx2RIS , eod_r_Tx2RIS ); 60 | V_Tx2RIS = 1 *Vt; 61 | H_Tx2RIS = 1 *Ht; 62 | V_Tx2RIS_mat(1, i) = V_Tx2RIS; 63 | H_Tx2RIS_mat(1, i) = H_Tx2RIS; 64 | end 65 | % RIS2Rx 66 | for j = 1:no_ant_rx 67 | rx_position_tmp2 = rx_position_tmp{j}; 68 | rx_Vtmp2 = rx_Vtmp{j}; 69 | rx_Htmp2 = rx_Htmp{j}; 70 | % Angle of RIS2Rx 71 | [AOD_RIS2Rx, AOA_RIS2Rx] = CalculateAngle( ris_position, rx_position_tmp2 ); % Angles between RIS and Rx 72 | aod_r_RIS2Rx = AOD_RIS2Rx(2).'*pi/180; % phi_s 73 | aoa_r_RIS2Rx = AOA_RIS2Rx(2).'*pi/180; 74 | eod_r_RIS2Rx = AOD_RIS2Rx(1).'*pi/180; % theta_s 75 | eoa_r_RIS2Rx = AOA_RIS2Rx(1).'*pi/180; 76 | aod_r_RIS2Rx_mat(1, j) = aod_r_RIS2Rx; 77 | eod_r_RIS2Rx_mat(1, j) = eod_r_RIS2Rx; 78 | % Signal of RIS2Rx 79 | [ Vr, Hr ] = LinearInterpolate( rx_Vtmp2, rx_Htmp2, rx , aoa_r_RIS2Rx , eoa_r_RIS2Rx ); 80 | V_RIS2Rx = Vr *1; 81 | H_RIS2Rx = Hr *1; 82 | V_RIS2Rx_mat(1, j) = V_RIS2Rx; 83 | H_RIS2Rx_mat(1, j) = H_RIS2Rx; 84 | end 85 | 86 | % RIS scatter matrix corresponding to the angle of Tx and Rx 87 | % (Scatter Matrix is from C. A. Balanis, Advanced Engineering Electromagnetics. 88 | % 2nd ed. Hoboken, NJ, USA: Wiley, 2012, pp.591-599.) 89 | for i = 1:no_ant_tx 90 | V_Tx2RIS = V_Tx2RIS_mat(1, i); 91 | H_Tx2RIS = H_Tx2RIS_mat(1, i); 92 | aoa_r_Tx2RIS = aoa_r_Tx2RIS_mat(1, i); 93 | eoa_r_Tx2RIS = eoa_r_Tx2RIS_mat(1, i); 94 | for j = 1:no_ant_rx 95 | V_RIS2Rx = V_RIS2Rx_mat(1, j); 96 | H_RIS2Rx = H_RIS2Rx_mat(1, j); 97 | aod_r_RIS2Rx = aod_r_RIS2Rx_mat(1, j); 98 | eod_r_RIS2Rx = eod_r_RIS2Rx_mat(1, j); 99 | % Calculate scatter matrix 100 | X = (a_all*k/2) * sin(eod_r_RIS2Rx) * cos(aod_r_RIS2Rx); 101 | Y = (b_all*k/2) * (sin(eod_r_RIS2Rx) * sin(aod_r_RIS2Rx) - sin(eoa_r_Tx2RIS)); 102 | if isnan(sin(X)/X), Xsinc = 1; else Xsinc = sin(X)/X; end 103 | if isnan(sin(Y)/Y), Ysinc = 1; else Ysinc = sin(Y)/Y; end 104 | C = (2*a_all*b_all*k) * Xsinc * Ysinc; 105 | S_V2V = C * cos(eoa_r_Tx2RIS) * cos(eod_r_RIS2Rx) * cos(aod_r_RIS2Rx); 106 | S_V2H = C * cos(eoa_r_Tx2RIS) * sin(aod_r_RIS2Rx); 107 | S_H2V = -1j * C * cos(eod_r_RIS2Rx) * sin(aod_r_RIS2Rx); 108 | S_H2H = -1j * C * cos(aod_r_RIS2Rx); 109 | S_matrix = [S_V2V, S_H2V; S_V2H, S_H2H]; 110 | S_matrix_cell(j, i) = {S_matrix}; 111 | % Scatter coefficient 112 | Amp = V_RIS2Rx * (S_V2V*V_Tx2RIS - S_H2V*H_Tx2RIS) - H_RIS2Rx * (S_V2H*V_Tx2RIS - S_H2H*H_Tx2RIS); 113 | Amp_mat(j, i) = Amp; 114 | end 115 | end 116 | 117 | %% Phase (Path length is "i-th Tx -> RIS center -> j-th Rx") 118 | tx_position_tmp = tx_position(:); 119 | rx_position_tmp = rx_position(:); 120 | Phase_mat = zeros(no_ant_rx, no_ant_tx); 121 | for i = 1:no_ant_tx 122 | tx_position_tmp2 = tx_position_tmp{i}; % i-th Tx location 123 | vec_Tx2RIS = ris_position - tx_position_tmp2; 124 | len_Tx2RIS = sqrt( sum( vec_Tx2RIS.^2 ,1 ) ); 125 | for j = 1:no_ant_rx 126 | rx_position_tmp2 = rx_position_tmp{j}; % j-th Rx location 127 | vec_RIS2Rx = rx_position_tmp2 - ris_position; 128 | len_RIS2Rx = sqrt( sum( vec_RIS2Rx.^2 ,1 ) ); 129 | len_total = len_Tx2RIS + len_RIS2Rx; 130 | Phase = k * mod(len_total, lambda); 131 | Phase_mat(j, i) = Phase; 132 | end 133 | end 134 | 135 | %% Path Loss 136 | switch LossType 137 | case 'withloss' 138 | loss_dB_Tx2RIS_mat = zeros(no_ant_rx, no_ant_tx); 139 | loss_dB_RIS2Rx_mat = zeros(no_ant_rx, no_ant_tx); 140 | for i = 1:no_ant_tx 141 | tx_position_tmp2 = tx_position_tmp{i}; 142 | for j = 1:no_ant_rx 143 | rx_position_tmp2 = rx_position_tmp{j}; 144 | loss_dB_Tx2RIS = pathloss( tx_position_tmp2, ris_position, lambda ); 145 | loss_dB_RIS2Rx = pathloss( ris_position, rx_position_tmp2, lambda ); 146 | loss_dB_Tx2RIS_mat(j, i) = loss_dB_Tx2RIS; 147 | loss_dB_RIS2Rx_mat(j, i) = loss_dB_RIS2Rx; 148 | end 149 | end 150 | case 'noloss' % otherwise 151 | loss_dB_Tx2RIS_mat = zeros(no_ant_rx, no_ant_tx); 152 | loss_dB_RIS2Rx_mat = zeros(no_ant_rx, no_ant_tx); 153 | end 154 | loss_mat = (sqrt(10.^(0.1*-1*loss_dB_Tx2RIS_mat))) .* (sqrt(10.^(0.1*-1*loss_dB_RIS2Rx_mat))); 155 | 156 | %% Calculate Coeff. 157 | Coeff_mat = loss_mat .* Amp_mat .* exp(-1j*Phase_mat); 158 | 159 | end 160 | %% Pathloss 161 | function [ loss ] = pathloss( tx_position, rx_position, lambda ) 162 | txpos = tx_position; 163 | rxpos = rx_position; 164 | d_3d = sqrt(sum( (rxpos-txpos).^2 )); 165 | loss = 20 * log10(4*pi*d_3d / lambda); 166 | end 167 | %% Angle 168 | function [ AOD, AOA ] = CalculateAngle( T_position, R_position ) 169 | % Vector in Cart. coordinate 170 | X_vec = R_position(1) - T_position(1); 171 | Y_vec = R_position(2) - T_position(2); 172 | Z_vec = R_position(3) - T_position(3); 173 | 174 | angles = zeros( 4, 1 ); 175 | % AOD-Horizontal polarization 176 | angles(1,1) = atan2( Y_vec, X_vec ); % [–pi, pi] 177 | angles(1, isnan(angles(1,1)) ) = 0; 178 | % AOD-Vertical polarization 179 | angles(3,1) = atan2( Z_vec, sqrt(X_vec.^2 + Y_vec.^2) ); % [–pi, pi] 180 | angles(3, isnan(angles(3,1)) ) = 0; 181 | % AOA-Horizontal polarization 182 | angles(2,1) = pi + angles(1,1); 183 | % AOA-Vertical polarization 184 | angles(4,1) = -1 * angles(3,1); 185 | 186 | % Change to (0,360) deg. 187 | angles = angles * 180/pi; 188 | angles(1,1) = mod( angles(1,1) , 360); 189 | angles(2,1) = mod( angles(2,1) , 360); 190 | 191 | % AOD (1. V / 2. H) 192 | AOD(1,1) = angles(3,1); 193 | AOD(2,1) = angles(1,1); 194 | % AOA (1. V / 2. H) 195 | AOA(1,1) = angles(4,1); 196 | AOA(2,1) = angles(2,1); 197 | 198 | % Vertical polarization changes to (0,180) deg. 199 | AOD(1,1) = -1*AOD(1,1) + 90; 200 | AOA(1,1) = -1*AOA(1,1) + 90; 201 | % Horizontal polarization changes to (0,360) deg. 202 | AODtmp = AOD(2,1); 203 | AODtmp_idx = AODtmp < 0; 204 | AODtmp(AODtmp_idx) = AODtmp(AODtmp_idx) + 360; 205 | AOD(2,1) = AODtmp; 206 | AOAtmp = AOA(2,1); 207 | AOAtmp_idx = AOAtmp < 0; 208 | AOAtmp(AOAtmp_idx) = AOAtmp(AOAtmp_idx) + 360; 209 | AOA(2,1) = AOAtmp; 210 | end 211 | -------------------------------------------------------------------------------- /RIS array/ChangeGrid.m: -------------------------------------------------------------------------------- 1 | function AntData = ChangeGrid( AntData , Azi_grid , Ele_grid ) 2 | %% Set grid 3 | Ele = repmat( Ele_grid' , 1 , numel(Azi_grid) ); 4 | Azi = repmat( Azi_grid , numel(Ele_grid) , 1 ); 5 | EleIDX = Ele_grid <= max(AntData.elevation_grid) & Ele_grid >= min(AntData.elevation_grid); 6 | AziIDX = Azi_grid <= max(AntData.azimuth_grid) & Azi_grid >= min(AntData.azimuth_grid); 7 | [V, H, T] = LinearInterpolateGrid( AntData , Azi(EleIDX,AziIDX) , Ele(EleIDX,AziIDX) ); 8 | %% Output 9 | AntData.elevation_grid = Ele_grid(EleIDX); 10 | AntData.azimuth_grid = Azi_grid(AziIDX); 11 | AntData.V = V; 12 | AntData.H = H; 13 | AntData.T = T; 14 | AntData.no_el = length(AntData.elevation_grid); 15 | AntData.no_az = length(AntData.azimuth_grid); 16 | end 17 | -------------------------------------------------------------------------------- /RIS array/ControlRIS_BGA.m: -------------------------------------------------------------------------------- 1 | function [ Coeff ] = ControlRIS_BGA( AntData, Coeff_scatter, Coeff_reflect_RIS, Coeff_RIS2Rx, Coeff_Tx2RIS, Coeff_LOS ); 2 | %% BGA 3 | %%% Input 4 | ris_initial_diag = AntData.ris.initial_diag; 5 | ris_num = AntData.ris.no_ant; % Number of RIS antennas 6 | ris_size = AntData.ris.size; 7 | Tr = 100; 8 | Tg = 2; 9 | state_need = 1:16; % DPS state needed to be controlled 10 | Bbit = state_need; 11 | state_num = length(Bbit); 12 | bit_num = log10(state_num) / log10(2); 13 | codebook_num = (2^bit_num)^ris_num; 14 | %%% Initialize 15 | Br = ones(1, ris_num); 16 | Btmp = ones(1, ris_num); 17 | 18 | %% DPS Setup 19 | DPS_phase = AntData.DPS.phase; 20 | DPS_phase(DPS_phase<-360) = DPS_phase(DPS_phase<-360)+360; 21 | DPS_phase(DPS_phase<-360) = DPS_phase(DPS_phase<-360)+360; 22 | DPS_loss = AntData.DPS.loss; 23 | DPS_phase_need = DPS_phase(1,state_need); 24 | DPS_loss_need = DPS_loss(1,state_need); 25 | DPS_data_need = [DPS_phase_need ; DPS_loss_need].'; 26 | DPS_data_need = sortrows(DPS_data_need, -1).'; 27 | DPS_need = sqrt(10.^(-0.1*DPS_data_need(2,:))) .* exp(1j*(DPS_data_need(1,:)/180*pi)); 28 | 29 | %% RMS 30 | % (1) 31 | DPS = DPS_need(Btmp); 32 | DPS_diag = diag(DPS(:)); 33 | Coeff_Tx2RIS2Rx = zeros(size(Coeff_RIS2Rx,1), size(Coeff_Tx2RIS,2)); 34 | for i = 1:size(Coeff_RIS2Rx,1) 35 | for j = 1:size(Coeff_Tx2RIS,2) 36 | Coeff_Tx2RIS2Rx(i, j) = Coeff_RIS2Rx(i,:) * DPS_diag * ris_initial_diag * Coeff_Tx2RIS(:,j); 37 | end 38 | end 39 | Coeff = Coeff_Tx2RIS2Rx + ... 40 | repmat(Coeff_scatter, size(Coeff_Tx2RIS2Rx)) + ... 41 | repmat(Coeff_reflect_RIS, size(Coeff_Tx2RIS2Rx)); %%% Combine all coefficients 42 | Coeff_need = Coeff; 43 | P = abs(Coeff).^2; 44 | [ Coeff_need, P, Br ] = RMS( Br, Tr, ris_num, state_num, DPS_need, Coeff_RIS2Rx, Coeff_Tx2RIS, ... 45 | ris_initial_diag, Coeff_scatter, Coeff_reflect_RIS, Coeff_need, Coeff_LOS, P ); 46 | % (5) 47 | Bg = Br; 48 | %% GS 49 | [ Coeff_need, P, Bg ] = GS( Bg, Bbit, Tg, ris_num, state_num, DPS_need, Coeff_RIS2Rx, Coeff_Tx2RIS, ... 50 | ris_initial_diag, Coeff_scatter, Coeff_reflect_RIS, Coeff_need, Coeff_LOS, P ); 51 | % (9) 52 | B = Bg; 53 | B_reshape = reshape(flip(B), ris_size); 54 | %% Results 55 | Coeff = Coeff_need; 56 | 57 | end 58 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 59 | function [ Coeff_need, P, Br ] = RMS( Br, Tr, ris_num, state_num, DPS_need, Coeff_RIS2Rx, Coeff_Tx2RIS, ... 60 | ris_initial_diag, Coeff_scatter, Coeff_reflect_RIS, Coeff_need, Coeff_LOS, P ) 61 | for tr = 1:Tr 62 | % (2) 63 | Btmp = []; 64 | for i = 1:ris_num 65 | rand( 'state', tr*i ); 66 | Btmp_value = randi(state_num); 67 | Btmp = [Btmp, Btmp_value]; 68 | end 69 | % (3) 70 | DPS = DPS_need( flip(Btmp) ); 71 | DPS_diag = diag(DPS(:)); 72 | Coeff_Tx2RIS2Rx = zeros(size(Coeff_RIS2Rx,1), size(Coeff_Tx2RIS,2)); 73 | for i = 1:size(Coeff_RIS2Rx,1) 74 | for j = 1:size(Coeff_Tx2RIS,2) 75 | Coeff_Tx2RIS2Rx(i, j) = Coeff_RIS2Rx(i,:) * DPS_diag * ris_initial_diag * Coeff_Tx2RIS(:,j); 76 | end 77 | end 78 | Coeff = Coeff_Tx2RIS2Rx + ... 79 | repmat(Coeff_scatter, size(Coeff_Tx2RIS2Rx)) + ... 80 | repmat(Coeff_reflect_RIS, size(Coeff_Tx2RIS2Rx)); %%% Combine all coefficients 81 | Ptmp = abs(Coeff).^2; 82 | % Stack data 83 | AbsCoeff_org = abs(Coeff_need + Coeff_LOS); 84 | AbsCoeff_new = abs(Coeff + Coeff_LOS); 85 | if (Ptmp > P) 86 | Coeff_need = Coeff; 87 | end 88 | % (4) 89 | if (Ptmp > P) 90 | P = Ptmp; 91 | Br = Btmp; 92 | end 93 | end 94 | end 95 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 96 | function [ Coeff_need, P, Bg ] = GS( Bg, Bbit, Tg, ris_num, state_num, DPS_need, Coeff_RIS2Rx, Coeff_Tx2RIS, ... 97 | ris_initial_diag, Coeff_scatter, Coeff_reflect_RIS, Coeff_need, Coeff_LOS, P ) 98 | for tg = 1:Tg 99 | for nris = 1:ris_num 100 | Btmp = Bg; 101 | for mbit = 1:state_num 102 | % (6) 103 | Btmp(nris) = Bbit(mbit); 104 | % (7) 105 | DPS = DPS_need( flip(Btmp) ); 106 | DPS_diag = diag(DPS(:)); 107 | Coeff_Tx2RIS2Rx = zeros(size(Coeff_RIS2Rx,1), size(Coeff_Tx2RIS,2)); 108 | for i = 1:size(Coeff_RIS2Rx,1) 109 | for j = 1:size(Coeff_Tx2RIS,2) 110 | Coeff_Tx2RIS2Rx(i, j) = Coeff_RIS2Rx(i,:) * DPS_diag * ris_initial_diag * Coeff_Tx2RIS(:,j); 111 | end 112 | end 113 | Coeff = Coeff_Tx2RIS2Rx + ... 114 | repmat(Coeff_scatter, size(Coeff_Tx2RIS2Rx)) + ... 115 | repmat(Coeff_reflect_RIS, size(Coeff_Tx2RIS2Rx)); %%% Combine all coefficients 116 | Ptmp = abs(Coeff).^2; 117 | % Stack data 118 | AbsCoeff_org = abs(Coeff_need + Coeff_LOS); 119 | AbsCoeff_new = abs(Coeff + Coeff_LOS); 120 | if (Ptmp > P) 121 | Coeff_need = Coeff; 122 | end 123 | % (8) 124 | if (Ptmp > P) 125 | P = Ptmp; 126 | Bg = Btmp; 127 | end 128 | end 129 | end 130 | end 131 | end 132 | -------------------------------------------------------------------------------- /RIS array/ControlRIS_BGApolar.m: -------------------------------------------------------------------------------- 1 | function [ Coeff ] = ControlDPS_BGApolar( AntData, Coeff_scatter, Coeff_reflect_RIS, Coeff_RIS2Rx, Coeff_Tx2RIS, Coeff_LOS ); 2 | %% BGA 3 | %%% Input 4 | ris_initial_diag = AntData.ris.initial_diag; 5 | ris_num = AntData.ris.no_ant; % Number of RIS antennas 6 | ris_size = AntData.ris.size; 7 | Tr = 100; 8 | Tg = 2; 9 | state_need = 1:16; % DPS state needed to be controlled 10 | Bbit = state_need; 11 | state_num = length(Bbit); 12 | bit_num = log10(state_num) / log10(2); 13 | codebook_num = (2^bit_num)^ris_num; 14 | polar_need = [0,45,90]; 15 | polar_num = length(polar_need); % Number of RIS polarization 16 | %%% Initialize 17 | Br = ones(1, ris_num); 18 | Br_pol = zeros(ris_num, 3); 19 | Btmp = ones(1, ris_num); 20 | Btmp_pol = zeros(ris_num, 3); 21 | Coeff_all_stack = []; 22 | Pol_axis = 3; 23 | %% DPS Setup 24 | DPS_phase = AntData.DPS.phase; 25 | DPS_phase(DPS_phase<-360) = DPS_phase(DPS_phase<-360)+360; 26 | DPS_phase(DPS_phase<-360) = DPS_phase(DPS_phase<-360)+360; 27 | DPS_loss = AntData.DPS.loss; 28 | DPS_phase_need = DPS_phase(1,state_need); 29 | DPS_loss_need = DPS_loss(1,state_need); 30 | DPS_data_need = [DPS_phase_need ; DPS_loss_need].'; 31 | DPS_data_need = sortrows(DPS_data_need, -1).'; 32 | DPS_need = sqrt(10.^(-0.1*DPS_data_need(2,:))) .* exp(1j*(DPS_data_need(1,:)/180*pi)); 33 | %% RMS 34 | % (1) 35 | DPS = DPS_need(Btmp); 36 | DPS_diag = diag(DPS(:)); 37 | Coeff_Tx2RIS2Rx = zeros(size(Coeff_RIS2Rx,1), size(Coeff_Tx2RIS,2)); 38 | for i = 1:size(Coeff_RIS2Rx,1) 39 | for j = 1:size(Coeff_Tx2RIS,2) 40 | Coeff_Tx2RIS2Rx(i, j) = Coeff_RIS2Rx(i,:) * DPS_diag * ris_initial_diag * Coeff_Tx2RIS(:,j); 41 | end 42 | end 43 | Coeff = Coeff_Tx2RIS2Rx + ... 44 | repmat(Coeff_scatter, size(Coeff_Tx2RIS2Rx)) + ... 45 | repmat(Coeff_reflect_RIS, size(Coeff_Tx2RIS2Rx)); %%% Combine all coefficients 46 | Coeff_need = Coeff; 47 | P = abs(Coeff).^2; 48 | for tr = 1:Tr 49 | % (2) 50 | Btmp = []; 51 | for i = 1:ris_num 52 | rand( 'state', tr*i ); 53 | Btmp_value = randi(state_num); 54 | Btmp = [Btmp, Btmp_value]; 55 | end 56 | % (3) 57 | DPS = DPS_need( flip(Btmp) ); 58 | DPS_diag = diag(DPS(:)); 59 | Coeff_Tx2RIS2Rx = zeros(size(Coeff_RIS2Rx,1), size(Coeff_Tx2RIS,2)); 60 | for i = 1:size(Coeff_RIS2Rx,1) 61 | for j = 1:size(Coeff_Tx2RIS,2) 62 | Coeff_Tx2RIS2Rx(i, j) = Coeff_RIS2Rx(i,:) * DPS_diag * ris_initial_diag * Coeff_Tx2RIS(:,j); 63 | end 64 | end 65 | Coeff = Coeff_Tx2RIS2Rx + ... 66 | repmat(Coeff_scatter, size(Coeff_Tx2RIS2Rx)) + ... 67 | repmat(Coeff_reflect_RIS, size(Coeff_Tx2RIS2Rx)); %%% Combine all coefficients 68 | Ptmp = abs(Coeff).^2; 69 | % Stack data 70 | if (Ptmp > P) 71 | Coeff_need = Coeff; 72 | end 73 | % (4) 74 | if (Ptmp > P) 75 | P = Ptmp; 76 | Br = Btmp; 77 | Br_pol = Btmp_pol; 78 | end 79 | end 80 | % (5) 81 | Bg = Br; 82 | Bg_pol = Br_pol; 83 | for i = 1:ris_num 84 | Bg_pol_tmp = Bg_pol(i,:); 85 | AntData.ris = RotateAntenna( AntData.ris, Bg_pol_tmp, i ); 86 | end 87 | %% GS 88 | for tg = 1:Tg 89 | for nris = 1:ris_num 90 | Btmp = Bg; 91 | Btmp_pol = Bg_pol; 92 | for mbit = 1:state_num 93 | for mpol = 1:polar_num 94 | % (6) 95 | Btmp(nris) = Bbit(mbit); 96 | Btmp_pol(nris, Pol_axis) = polar_need(mpol); 97 | % (7) 98 | %%% Polarization 99 | Btmp_pol_tmp = Btmp_pol(nris, :); 100 | AntData.ris = RotateAntenna( AntData.ris, Btmp_pol_tmp, nris ); 101 | Coeff_Tx2RIS = CalculateCC( AntData, AntData.tx, AntData.ris ); 102 | Coeff_RIS2Rx = CalculateCC( AntData, AntData.ris, AntData.rx ); 103 | %%% State 104 | DPS = DPS_need( flip(Btmp) ); 105 | DPS_diag = diag(DPS(:)); 106 | Coeff_Tx2RIS2Rx = zeros(size(Coeff_RIS2Rx,1), size(Coeff_Tx2RIS,2)); 107 | for i = 1:size(Coeff_RIS2Rx,1) 108 | for j = 1:size(Coeff_Tx2RIS,2) 109 | Coeff_Tx2RIS2Rx(i, j) = Coeff_RIS2Rx(i,:) * DPS_diag * ris_initial_diag * Coeff_Tx2RIS(:,j); 110 | end 111 | end 112 | Coeff = Coeff_Tx2RIS2Rx + ... 113 | repmat(Coeff_scatter, size(Coeff_Tx2RIS2Rx)) + ... 114 | repmat(Coeff_reflect_RIS, size(Coeff_Tx2RIS2Rx)); %%% Combine all coefficients 115 | Ptmp = abs(Coeff).^2; 116 | % Stack data 117 | if (Ptmp > P) 118 | Coeff_need = Coeff; 119 | end 120 | % (8) 121 | if (Ptmp > P) 122 | P = Ptmp; 123 | Bg = Btmp; 124 | Bg_pol = Btmp_pol; 125 | end 126 | % Recover polarization 127 | AntData.ris = RotateAntenna( AntData.ris, -1*Btmp_pol_tmp, nris ); 128 | end 129 | end 130 | end 131 | end 132 | % (9) 133 | B = Bg; 134 | B_pol = Bg_pol(:,Pol_axis); 135 | B_reshape = reshape(flip(B), ris_size); 136 | B_pol_reshape = reshape(flip(B_pol), ris_size); 137 | %% Results 138 | Coeff = Coeff_need; 139 | end 140 | 141 | -------------------------------------------------------------------------------- /RIS array/ControlRIS_DPSbeam.m: -------------------------------------------------------------------------------- 1 | function [ Coeff ] = ControlRIS_DPSbeam( AntData, Coeff_scatter, Coeff_reflect_RIS, Coeff_RIS2Rx, Coeff_Tx2RIS, Coeff_LOS ); 2 | %% DPS Setup 3 | DPS_phase = AntData.DPS.phase; 4 | DPS_phase(DPS_phase<-360) = DPS_phase(DPS_phase<-360) + 360; 5 | DPS_phase(DPS_phase<-360) = DPS_phase(DPS_phase<-360) + 360; 6 | DPS_phase = DPS_phase/180*pi; 7 | DPS_loss = AntData.DPS.loss; 8 | DPS_need = sqrt(10.^(-0.1*DPS_loss)) .* exp(1j*DPS_phase); 9 | 10 | %% Control DPS (Perfect beamforming with all phase information) 11 | ris_size = AntData.ris.size; 12 | Phase_LOS = angle(Coeff_LOS); 13 | Phase_Tx2RIS = angle(Coeff_Tx2RIS); 14 | Phase_RIS2Rx = angle(Coeff_RIS2Rx); 15 | Phase_Tx2RIS2Rx = reshape(Phase_Tx2RIS, ris_size) + reshape(Phase_RIS2Rx, ris_size); 16 | Phase_delta = repmat(Phase_LOS, ris_size) - Phase_Tx2RIS2Rx; 17 | 18 | %% Corresponding to the closest DPS's phase 19 | Phase_delta_mat = repmat(Phase_delta, [1,1,length(DPS_phase)]); 20 | DPS_phase_mat = repmat(reshape(DPS_phase,[1,1,length(DPS_phase)]), [ris_size(1),ris_size(2),1]); 21 | delta_mat = abs(Phase_delta_mat - DPS_phase_mat); 22 | [~, DPSstate] = min(delta_mat, [], 3); 23 | DPS = DPS_need(DPSstate); 24 | 25 | %% Calculate coefficients 26 | DPS_diag = diag(DPS(:)); 27 | Coeff_Tx2RIS2Rx = zeros(size(Coeff_RIS2Rx,1), size(Coeff_Tx2RIS,2)); 28 | for i = 1:size(Coeff_RIS2Rx,1) 29 | for j = 1:size(Coeff_Tx2RIS,2) 30 | Coeff_Tx2RIS2Rx(i, j) = Coeff_RIS2Rx(i,:) * DPS_diag * Coeff_Tx2RIS(:,j); 31 | end 32 | end 33 | %%% Combine all coefficients 34 | Coeff = Coeff_Tx2RIS2Rx + ... 35 | repmat(Coeff_scatter, size(Coeff_Tx2RIS2Rx)) + ... 36 | repmat(Coeff_reflect_RIS, size(Coeff_Tx2RIS2Rx)); 37 | end 38 | 39 | -------------------------------------------------------------------------------- /RIS array/ControlRIS_Perfectbeam.m: -------------------------------------------------------------------------------- 1 | function [ Coeff ] = ControlRIS_Perfectbeam( AntData, Coeff_scatter, Coeff_reflect_RIS, Coeff_RIS2Rx, Coeff_Tx2RIS, Coeff_LOS ); 2 | %% Control DPS (Perfect beamforming with all phase information) 3 | ris_size = AntData.ris.size; 4 | InjEff = 1 *ones(ris_size); 5 | Phase_LOS = angle(Coeff_LOS); 6 | Phase_Tx2RIS = angle(Coeff_Tx2RIS); 7 | Phase_RIS2Rx = angle(Coeff_RIS2Rx); 8 | Phase_Tx2RIS2Rx = reshape(Phase_Tx2RIS, ris_size) + reshape(Phase_RIS2Rx, ris_size); 9 | Phase_delta = repmat(Phase_LOS, ris_size) - Phase_Tx2RIS2Rx; 10 | DPS = InjEff .* exp(1j*Phase_delta); 11 | 12 | %% Calculate coefficients 13 | DPS_diag = diag(DPS(:)); 14 | Coeff_Tx2RIS2Rx = zeros(size(Coeff_RIS2Rx,1), size(Coeff_Tx2RIS,2)); 15 | for i = 1:size(Coeff_RIS2Rx,1) 16 | for j = 1:size(Coeff_Tx2RIS,2) 17 | Coeff_Tx2RIS2Rx(i, j) = Coeff_RIS2Rx(i,:) * DPS_diag * Coeff_Tx2RIS(:,j); 18 | end 19 | end 20 | %%% Combine all coefficients 21 | Coeff = Coeff_Tx2RIS2Rx + ... 22 | repmat(Coeff_scatter, size(Coeff_Tx2RIS2Rx)) + ... 23 | repmat(Coeff_reflect_RIS, size(Coeff_Tx2RIS2Rx)); 24 | end 25 | 26 | -------------------------------------------------------------------------------- /RIS array/GetCC_LOS.m: -------------------------------------------------------------------------------- 1 | function [ Coeff ] = GetCC_LOS( AntData, TxRot, RxRot ) 2 | %% Grid 3 | ele = AntData.elevation_range; 4 | azi = AntData.azimuth_range; 5 | % Change grid with interpolate (Rough) 6 | elevation_grid = ele(1):(10/180*pi):ele(2); 7 | azimuth_grid = azi(1):(10/180*pi):azi(2); 8 | AntData.tx = ChangeGrid( AntData.tx , azimuth_grid , elevation_grid ); 9 | AntData.rx = ChangeGrid( AntData.rx , azimuth_grid , elevation_grid ); 10 | 11 | % Change grid with interpolate (Need) 12 | elevation_grid = ele(1):(1/180*pi):ele(2); 13 | azimuth_grid = azi(1):(1/180*pi):azi(2); 14 | AntData.tx = ChangeGrid( AntData.tx , azimuth_grid , elevation_grid ); 15 | AntData.rx = ChangeGrid( AntData.rx , azimuth_grid , elevation_grid ); 16 | 17 | %% Rotate pattern 18 | TxRotIDX_num = length(TxRot); 19 | for i = 1:TxRotIDX_num 20 | TxRotNeed = TxRot{i}; 21 | AntData.tx = RotateAntenna( AntData.tx, TxRotNeed ); 22 | end 23 | RxRotIDX_num = length(RxRot); 24 | for i = 1:RxRotIDX_num 25 | RxRotNeed = RxRot{i}; 26 | AntData.rx = RotateAntenna( AntData.rx, RxRotNeed ); 27 | end 28 | 29 | %% Calculate channel coefficient 30 | Coeff = CalculateCC( AntData, AntData.tx, AntData.rx ); 31 | 32 | end 33 | 34 | -------------------------------------------------------------------------------- /RIS array/GetCC_RIS.m: -------------------------------------------------------------------------------- 1 | function [ Coeff ] = GetCC_RIS( Coeff_LOS, AntData, RISLoc, TxRot, RxRot, RISRot ) 2 | %% Grid 3 | ele = AntData.elevation_range; 4 | azi = AntData.azimuth_range; 5 | % Change grid with interpolate (Rough) 6 | elevation_grid = ele(1):(10/180*pi):ele(2); 7 | azimuth_grid = azi(1):(10/180*pi):azi(2); 8 | AntData.tx = ChangeGrid( AntData.tx , azimuth_grid , elevation_grid ); 9 | AntData.rx = ChangeGrid( AntData.rx , azimuth_grid , elevation_grid ); 10 | AntData.ris = ChangeGrid( AntData.ris , azimuth_grid , elevation_grid ); 11 | 12 | % Change grid with interpolate (Need) 13 | elevation_grid = ele(1):(1/180*pi):ele(2); 14 | azimuth_grid = azi(1):(1/180*pi):azi(2); 15 | AntData.tx = ChangeGrid( AntData.tx , azimuth_grid , elevation_grid ); 16 | AntData.rx = ChangeGrid( AntData.rx , azimuth_grid , elevation_grid ); 17 | AntData.ris = ChangeGrid( AntData.ris , azimuth_grid , elevation_grid ); 18 | 19 | %% Rotate pattern 20 | TxRotIDX_num = length(TxRot); 21 | for i = 1:TxRotIDX_num 22 | TxRotNeed = TxRot{i}; 23 | AntData.tx = RotateAntenna( AntData.tx, TxRotNeed ); 24 | end 25 | RxRotIDX_num = length(RxRot); 26 | for i = 1:RxRotIDX_num 27 | RxRotNeed = RxRot{i}; 28 | AntData.rx = RotateAntenna( AntData.rx, RxRotNeed ); 29 | end 30 | RISRotIDX_num = length(RISRot); 31 | for i = 1:RISRotIDX_num 32 | RISRotNeed = RISRot{i}; 33 | AntData.ris = RotateAntenna( AntData.ris, RISRotNeed ); 34 | end 35 | 36 | %% Calculate channel coefficient 37 | % Calculate Scatter coefficient on RIS 38 | ScatterEff = 11.2; 39 | Coeff_scatter = CalculateScatter( AntData, RISLoc ); 40 | Coeff_scatter = ScatterEff * Coeff_scatter; 41 | 42 | % Calculate Reflection coefficient on RIS 43 | RefEff = 8; 44 | Coeff_reflect_RIS = CalculateReflect( AntData, RISLoc ); 45 | Coeff_reflect_RIS = RefEff * Coeff_reflect_RIS; 46 | 47 | % Calculate RIS channel coefficient 48 | Coeff_Tx2RIS = CalculateCC( AntData, AntData.tx, AntData.ris ); 49 | Coeff_RIS2Rx = CalculateCC( AntData, AntData.ris, AntData.rx ); 50 | 51 | % Random initial phase of RIS 52 | ris_initial = exp(1j*(2*pi)*repmat(5/12,AntData.ris.no_ant, 1)); 53 | ris_initial_diag = diag(ris_initial(:)); 54 | AntData.ris.initial_diag = ris_initial_diag; 55 | 56 | % Control DPS 57 | switch AntData.CtlMethod 58 | case 'Perfect_beam' % Without random initial phase of RIS 59 | Coeff = ControlRIS_Perfectbeam( AntData, Coeff_scatter, Coeff_reflect_RIS, Coeff_RIS2Rx, Coeff_Tx2RIS, Coeff_LOS ); 60 | case 'DPS_beam' % Without random initial phase of RIS 61 | Coeff = ControlRIS_DPSbeam( AntData, Coeff_scatter, Coeff_reflect_RIS, Coeff_RIS2Rx, Coeff_Tx2RIS, Coeff_LOS ); 62 | case 'BGA' 63 | Coeff = ControlRIS_BGA( AntData, Coeff_scatter, Coeff_reflect_RIS, Coeff_RIS2Rx, Coeff_Tx2RIS, Coeff_LOS ); 64 | case 'BGA_polar' 65 | Coeff = ControlRIS_BGApolar( AntData, Coeff_scatter, Coeff_reflect_RIS, Coeff_RIS2Rx, Coeff_Tx2RIS, Coeff_LOS ); 66 | end 67 | disp([ 'Controlling algorithm: ', AntData.CtlMethod ]); 68 | end 69 | 70 | -------------------------------------------------------------------------------- /RIS array/LinearInterpolate.m: -------------------------------------------------------------------------------- 1 | function [ V, H ] = LinearInterpolate( V, H, AntData, azimuth_meshgrid_new, elevation_meshgrid_new ) 2 | %% Linear Interpolation 3 | azimuth_grid = AntData.azimuth_grid; 4 | elevation_grid = AntData.elevation_grid; 5 | azimuth_meshgrid = repmat(azimuth_grid, [length(elevation_grid),1]); 6 | elevation_meshgrid = repmat(elevation_grid.', [1,length(azimuth_grid)]); 7 | V_new = interp2(azimuth_meshgrid, elevation_meshgrid, V, azimuth_meshgrid_new, elevation_meshgrid_new, 'linear'); 8 | V_new(:,end) = V_new(:,1); 9 | H_new = interp2(azimuth_meshgrid, elevation_meshgrid, H, azimuth_meshgrid_new, elevation_meshgrid_new, 'linear'); 10 | H_new(:,end) = H_new(:,1); 11 | %% Output 12 | V = V_new; 13 | H = H_new; 14 | end 15 | 16 | -------------------------------------------------------------------------------- /RIS array/LinearInterpolateGrid.m: -------------------------------------------------------------------------------- 1 | function [ V, H, T ] = LinearInterpolateGrid( AntData, azimuth_meshgrid_new, elevation_meshgrid_new ) 2 | %% Linear Interpolation 3 | azimuth_grid = AntData.azimuth_grid; 4 | elevation_grid = AntData.elevation_grid; 5 | azimuth_meshgrid = repmat(azimuth_grid, [length(elevation_grid),1]); 6 | elevation_meshgrid = repmat(elevation_grid.', [1,length(azimuth_grid)]); 7 | V = AntData.V; 8 | H = AntData.H; 9 | Vtmp = V(:); 10 | Htmp = H(:); 11 | no_ant = AntData.no_ant; 12 | Vcell = cell(no_ant,1); 13 | Hcell = cell(no_ant,1); 14 | Tcell = cell(no_ant,1); 15 | for i = 1:no_ant 16 | Vtmp_i = Vtmp{i}; 17 | V_new = interp2(azimuth_meshgrid, elevation_meshgrid, Vtmp_i, ... 18 | azimuth_meshgrid_new, elevation_meshgrid_new, 'linear'); 19 | V_new(:,end) = V_new(:,1); 20 | Vcell(i) = {V_new}; 21 | Htmp_i = Htmp{i}; 22 | H_new = interp2(azimuth_meshgrid, elevation_meshgrid, Htmp_i, ... 23 | azimuth_meshgrid_new, elevation_meshgrid_new, 'linear'); 24 | H_new(:,end) = H_new(:,1); 25 | Hcell(i) = {H_new}; 26 | T_new = sqrt(V_new.^2 + H_new.^2); 27 | Tcell(i) = {T_new}; 28 | end 29 | Vcell = reshape(Vcell, size(V)); 30 | Hcell = reshape(Hcell, size(H)); 31 | Tcell = reshape(Tcell, size(H)); 32 | %% Output 33 | V = Vcell; 34 | H = Hcell; 35 | T = Tcell; 36 | end 37 | 38 | -------------------------------------------------------------------------------- /RIS array/LoadParameter.m: -------------------------------------------------------------------------------- 1 | function [ AntData ] = LoadParameter( file, TxLoc, RxLoc, RISLoc ) 2 | %% Setup 3 | TxPower_dBm = 0; % unit: dBm. 4 | AntData.TxPower_dBm = TxPower_dBm; 5 | AntData.TxPower = 1e-3 * 10^(TxPower_dBm/10); % unit: W. 6 | AntData.LossType = 'withloss'; % 'withloss' / 'noloss' 7 | AntData.freq = 3.5e9; % Center Frequency (unit: Hz) 8 | 9 | elevation_range = [0, pi]; 10 | azimuth_range = [0, 2*pi]; 11 | AntData.elevation_range = elevation_range; 12 | AntData.azimuth_range = azimuth_range; 13 | 14 | if exist('RISLoc','var') 15 | AntNum = 3; 16 | else 17 | AntNum = 2; 18 | end 19 | %% Load radiation pattern 20 | startIDX = 2; 21 | path_now = pwd; 22 | path_data = [path_now,'\', file]; 23 | cd([path_data]); 24 | listDateTMP = dir; 25 | listDate = cell((length(listDateTMP)-2), 2); 26 | for i=1:size(listDate,1) 27 | listDate(i,1) = {listDateTMP(i+2).name}; 28 | end 29 | for i=1:size(listDate,1) 30 | filename = listDate{i,1}; 31 | ANTcsvTMP = xlsread([filename]); 32 | ANTcsv = ANTcsvTMP(startIDX:end , startIDX:end); 33 | listDate(i,2) = {ANTcsv}; clear ANTcsv 34 | end 35 | cd([path_now]); 36 | 37 | %% Digital Phase Shifter (DPS) 38 | phase = [-33.64, -61.63, -102.0, -142.1, ... 39 | -178.0, -225.7, -311.1, -365.5, ... 40 | -395.4, -423.8, -462.1, -508.4, ... 41 | -545.1, -596.2, -681.1, -733.9]; 42 | loss = [3.601, 3.516, 5.175, 7.309, ... 43 | 6.442, 7.578, 8.294, 6.973, ... 44 | 3.289, 3.336, 5.031, 7.238, ... 45 | 6.305, 7.194, 7.500, 6.228]; 46 | AntData.DPS.phase = phase; 47 | AntData.DPS.loss = loss; 48 | 49 | %% 50 | typeAll = {'tx','rx','ris'}; 51 | AntNeedAll = [1, 3, 2]; 52 | 53 | for i = 1:AntNum 54 | type = typeAll{1,i}; 55 | AntNeed = AntNeedAll(1,i); 56 | 57 | CustAntV = listDate(AntNeed + (size(listDate,1)/2),:); 58 | CustAntH = listDate(AntNeed,:); 59 | Vtmp = CustAntV{1,2}; 60 | Htmp = CustAntH{1,2}; 61 | Vtmp = sqrt(10.^(Vtmp/10)); 62 | Htmp = sqrt(10.^(Htmp/10)); 63 | no_elNeed = size(Vtmp, 1); 64 | no_azNeed = size(Vtmp, 2); 65 | elevation_gridNeed = linspace(elevation_range(1), elevation_range(2), no_elNeed); 66 | azimuth_gridNeed = linspace(azimuth_range(1), azimuth_range(2), no_azNeed); 67 | 68 | switch type 69 | case 'tx' 70 | AntData.tx.name = 'patch'; 71 | AntData.tx.V = {Vtmp}; 72 | AntData.tx.H = {Htmp}; 73 | AntData.tx.T = {sqrt(Vtmp.^2 + Htmp.^2)}; 74 | AntData.tx.position = {TxLoc}; 75 | AntData.tx.no_ant = 1; 76 | AntData.tx.no_el = no_elNeed; 77 | AntData.tx.no_az = no_azNeed; 78 | AntData.tx.elevation_grid = elevation_gridNeed; 79 | AntData.tx.azimuth_grid = azimuth_gridNeed; 80 | AntData.tx.normal = [0;0;1]; % Normal vector of Tx array 81 | AntData.tx.orient = [0;1;0]; % Orientation of Tx 82 | case 'rx' 83 | AntData.rx.name = 'patch'; 84 | AntData.rx.V = {Vtmp}; 85 | AntData.rx.H = {Htmp}; 86 | AntData.rx.T = {sqrt(Vtmp.^2 + Htmp.^2)}; 87 | AntData.rx.position = {RxLoc}; 88 | AntData.rx.no_ant = 1; 89 | AntData.rx.no_el = no_elNeed; 90 | AntData.rx.no_az = no_azNeed; 91 | AntData.rx.elevation_grid = elevation_gridNeed; 92 | AntData.rx.azimuth_grid = azimuth_gridNeed; 93 | AntData.rx.normal = [0;0;1]; % Normal vector of Rx array 94 | AntData.rx.orient = [0;1;0]; % Orientation of Rx 95 | case 'ris' 96 | AntData.ris.name = 'patch'; 97 | AntData.ris.V = {Vtmp}; 98 | AntData.ris.H = {Htmp}; 99 | AntData.ris.T = {sqrt(Vtmp.^2 + Htmp.^2)}; 100 | AntData.ris.position = {RISLoc}; 101 | AntData.ris.no_ant = 1; 102 | AntData.ris.no_el = no_elNeed; 103 | AntData.ris.no_az = no_azNeed; 104 | AntData.ris.elevation_grid = elevation_gridNeed; 105 | AntData.ris.azimuth_grid = azimuth_gridNeed; 106 | AntData.ris.area_a = 0.094; % unit: m. 107 | AntData.ris.area_b = 0.073; 108 | AntData.ris.normal = [0;0;1]; % Normal vector of RIS array 109 | AntData.ris.orient = [0;1;0]; % Orientation of RIS 110 | end 111 | end 112 | %% 113 | TxRot = {[-10, 0, 0], [0, 10, 0]}; % Rotate in order. Unit: degree 114 | RxRot = {[-10, 0, 0], [0, 10, 0]}; % Rotate in order. Unit: degree 115 | RISRot = {[-10, 0, 0], [0, 10, 0]}; % Rotate in order. Unit: degree 116 | TxRotIDX_num = length(TxRot); 117 | for i = 1:TxRotIDX_num 118 | TxRotNeed = TxRot{i}; 119 | AntData.tx = TuneRotateAntenna( AntData.tx, TxRotNeed ); 120 | end 121 | RxRotIDX_num = length(RxRot); 122 | for i = 1:RxRotIDX_num 123 | RxRotNeed = RxRot{i}; 124 | AntData.rx = TuneRotateAntenna( AntData.rx, RxRotNeed ); 125 | end 126 | RISRotIDX_num = length(RISRot); 127 | for i = 1:RISRotIDX_num 128 | RISRotNeed = RISRot{i}; 129 | AntData.ris = TuneRotateAntenna( AntData.ris, RISRotNeed ); 130 | end 131 | 132 | end 133 | function [ AntData ] = TuneRotateAntenna( AntData, rot_angle ) 134 | %% Setup 135 | no_ant = AntData.no_ant; 136 | 137 | % Get the angles. 138 | phi = AntData.azimuth_grid; 139 | theta = AntData.elevation_grid'; 140 | no_az = AntData.no_az; 141 | no_el = AntData.no_el; 142 | 143 | % Change the unit from degree to rad. 144 | rot_angle = rot_angle/180*pi; 145 | 146 | %% Rotation matrix 147 | % Calculate the rotation matrix. 148 | rx = rot_angle(1); 149 | ry = rot_angle(2); 150 | rz = rot_angle(3); 151 | rot = zeros(3,3); 152 | rot(1,1) = cos(rz) * cos(ry); 153 | rot(2,1) = sin(rz) * cos(ry); 154 | rot(3,1) = -1 * sin(ry); 155 | rot(1,2) = cos(rz) * sin(ry) * sin(rx) - sin(rz) * cos(rx); 156 | rot(2,2) = sin(rz) * sin(ry) * sin(rx) + cos(rz) * cos(rx); 157 | rot(3,2) = cos(ry) * sin(rx); 158 | rot(1,3) = cos(rz) * sin(ry) * cos(rx) + sin(rz) * sin(rx); 159 | rot(2,3) = sin(rz) * sin(ry) * cos(rx) - cos(rz) * sin(rx); 160 | rot(3,3) = cos(ry) * cos(rx); 161 | 162 | %% Theta and Phi of signal direction in the global and local coordinate system 163 | % Change Theta from [0, pi] to [pi/2, -pi/2]. 164 | theta_mat = repmat(theta, [1, length(phi)]); 165 | theta_mat = -1*theta_mat + pi/2; 166 | % Change Phi from [0, 2*pi] to [pi, -pi]. 167 | phiTMP = phi; 168 | phiTMP_idx = phiTMP >= pi; %%% 169 | phiTMP(phiTMP_idx) = phiTMP(phiTMP_idx) - 2*pi; 170 | phi_mat = repmat(phiTMP, [length(theta), 1]); 171 | % Transform from spherical coordinates into Cartesian coordinates. 172 | [ Fx, Fy, Fz ] = sph2cart(phi_mat, theta_mat, 1e10); 173 | 174 | % Rotation of signal direction 175 | Fx_r = rot(1,1)*Fx + rot(2,1)*Fy +rot(3,1)*Fz; % Transpose 176 | Fy_r = rot(1,2)*Fx + rot(2,2)*Fy +rot(3,2)*Fz; 177 | Fz_r = rot(1,3)*Fx + rot(2,3)*Fy +rot(3,3)*Fz; 178 | 179 | % Transforme from Cartesian coordinates into spherical coordinates. 180 | [phi_mat_new, theta_mat_new] = cart2sph( Fx_r, Fy_r, Fz_r ); % [pi, -pi] and [pi/2, -pi/2]. 181 | % The pattern is not defined when the theta > 90 degree and < -90 degree. 182 | err_limit = 1e-5; 183 | theta_out_idx = theta_mat_new < -pi/2 + err_limit; 184 | theta_mat_new(theta_out_idx) = -pi/2 + err_limit; 185 | theta_out_idx = theta_mat_new > pi/2 - err_limit; 186 | theta_mat_new(theta_out_idx) = pi/2 - err_limit; 187 | % Change Theta from [pi/2, -pi/2] to [0, pi]. 188 | theta_mat_new = -1*theta_mat_new + pi/2; 189 | % Change Phi from [pi, -pi] to [0, 2*pi]. 190 | phi_mat_new_pi_idx = phi_mat_new < 0; 191 | phi_mat_new(phi_mat_new_pi_idx) = phi_mat_new(phi_mat_new_pi_idx) + 2*pi; 192 | 193 | %% Transformation matrix 194 | % Global coordinate system in theta direction. 195 | T_theta2x_g = cos(theta) * cos(phi); 196 | T_theta2y_g = cos(theta) * sin(phi); 197 | T_theta2z_g = -1 * sin(theta) * ones(1,no_az); 198 | 199 | % Global coordinate system in phi direction. 200 | T_phi2x_g = ones(no_el,1) * -1 * sin(phi); 201 | T_phi2y_g = ones(no_el,1) * cos(phi); 202 | T_phi2z_g = zeros( no_el , no_az ); 203 | 204 | % Local coordinate system in theta direction. 205 | T_theta2x_l = cos(theta_mat_new) .* cos(phi_mat_new); 206 | T_theta2y_l = cos(theta_mat_new) .* sin(phi_mat_new); 207 | T_theta2z_l = -1 * sin(theta_mat_new); 208 | 209 | % Local coordinate system in phi direction. 210 | T_phi2x_l = -1 * sin(phi_mat_new); 211 | T_phi2y_l = cos(phi_mat_new); 212 | T_phi2z_l = zeros( no_el , no_az ); 213 | 214 | %% Polarization rotation matrix 215 | T_theta2x_tmp = rot(1,1)*T_theta2x_l + rot(1,2)*T_theta2y_l + rot(1,3)*T_theta2z_l; 216 | T_theta2y_tmp = rot(2,1)*T_theta2x_l + rot(2,2)*T_theta2y_l + rot(2,3)*T_theta2z_l; 217 | T_theta2z_tmp = rot(3,1)*T_theta2x_l + rot(3,2)*T_theta2y_l + rot(3,3)*T_theta2z_l; 218 | T_phi2x_tmp = rot(1,1)*T_phi2x_l + rot(1,2)*T_phi2y_l + rot(1,3)*T_phi2z_l; 219 | T_phi2y_tmp = rot(2,1)*T_phi2x_l + rot(2,2)*T_phi2y_l + rot(2,3)*T_phi2z_l; 220 | T_phi2z_tmp = rot(3,1)*T_phi2x_l + rot(3,2)*T_phi2y_l + rot(3,3)*T_phi2z_l; 221 | Mo_11 = T_theta2x_tmp.*T_theta2x_g + T_theta2y_tmp.*T_theta2y_g + T_theta2z_tmp.*T_theta2z_g; 222 | Mo_12 = T_phi2x_tmp.*T_theta2x_g + T_phi2y_tmp.*T_theta2y_g + T_phi2z_tmp.*T_theta2z_g; 223 | Mo_21 = -1*Mo_12; 224 | Mo_22 = Mo_11; 225 | 226 | %% Reading the original pattern at the rotated signal direction 227 | [ V_org, H_org, T_org ] = LinearInterpolateGrid( AntData , phi_mat_new , theta_mat_new ); 228 | 229 | %% Transformation of the polarization 230 | Vtmp = V_org(:); 231 | Htmp = H_org(:); 232 | Vcell = cell(no_ant,1); 233 | Hcell = cell(no_ant,1); 234 | Tcell = cell(no_ant,1); 235 | for i = 1:no_ant 236 | Vtmp_i = Vtmp{i}; 237 | Htmp_i = Htmp{i}; 238 | V_new = Mo_11.*Vtmp_i + Mo_12.*Htmp_i; 239 | H_new = Mo_21.*Vtmp_i + Mo_22.*Htmp_i; 240 | T_new = sqrt(V_new.^2 + H_new.^2); 241 | Vcell(i) = {V_new}; 242 | Hcell(i) = {H_new}; 243 | Tcell(i) = {T_new}; 244 | end 245 | Vcell = reshape(Vcell, size(V_org)); 246 | Hcell = reshape(Hcell, size(H_org)); 247 | Tcell = reshape(Tcell, size(T_org)); 248 | 249 | %% Output 250 | AntData.V = Vcell; 251 | AntData.H = Hcell; 252 | AntData.T = Tcell; 253 | end 254 | 255 | 256 | -------------------------------------------------------------------------------- /RIS array/Main_RISarray_WithRotation.m: -------------------------------------------------------------------------------- 1 | % ========================================================================= 2 | % Article Title: 3 | % A Novel Channel Model for Reconfigurable Intelligent Surfaces 4 | % with Consideration of Polarization and Switch Impairments 5 | % (RIS array in Fig.12(b))(The case of receiver with rotation) 6 | % ------------------------------------------------------------------------- 7 | % Function: 8 | % CalculateCC.m / CalculateReflect.m / CalculateScatter.m / 9 | % ChangeGrid.m / LinearInterpolate.m / LinearInterpolateGrid.m / 10 | % LoadParameter.m / ArrayGenerate.m / 11 | % RodriguesRotVec.m / RotateAntenna.m / 12 | % ControlRIS_Perfectbeam.m / ControlRIS_DPSbeam.m / 13 | % ControlRIS_BGA.m / ControlRIS_BGApolar.m / 14 | % GetCC_LOS.m / GetCC_RIS.m 15 | % ------------------------------------------------------------------------- 16 | % Data: 17 | % Pattern file (AntH2.xlsx / AntH3.xlsx / AntH4.xlsx / 18 | % AntV2.xlsx / AntV3.xlsx / AntV4.xlsx) 19 | % ------------------------------------------------------------------------- 20 | % Copyright (c) 2023 De-Ming Chian and Chao-Kai Wen 21 | % E-mail: icefreeman123@gmail.com and chaokai.wen@mail.nsysu.edu.tw 22 | % Reference: QuaDriGa_2016.09.05_v1.4.8-571 23 | % ========================================================================= 24 | close all; clear all; clc 25 | %% Setup 26 | TxLoc = [ 0 ; 0 ; 0.8 ]; % Array center. Unit: m. 27 | RxLoc = [ 0 ; 0.2 ; 1.6 ]; % Array center. Unit: m. 28 | RISLoc = [ 0 ; 0 ; 0 ]; % Array center. Unit: m. 29 | AntData = LoadParameter( 'Pattern', TxLoc, RxLoc, RISLoc ); % Single antenna data 30 | 31 | TxRot = {[0, 90, 0], [0, 0, 90]}; % Rotate in order. Unit: degree 32 | RxRot = {[0, 90, 0], [0, 0, 90]}; % Rotate in order. Unit: degree 33 | RISRot = {[0, 90, 0], [180, 0, 0], [0, 0, -90]}; % Rotate in order. Unit: degree 34 | 35 | AntData.tx.size = [1, 1]; % Array size 36 | AntData.tx = ArrayGenerate( AntData, AntData.tx ); % Duplicate array data 37 | AntData.rx.size = [1, 1]; % Array size 38 | AntData.rx = ArrayGenerate( AntData, AntData.rx ); % Duplicate array data 39 | AntData.ris.size = [4, 4]; % Array size 40 | AntData.ris = ArrayGenerate( AntData, AntData.ris ); % Duplicate array data 41 | 42 | %%% Controlling algorithm: 43 | AntData.CtlMethod = 'Perfect_beam'; % Perfect_beam / DPS_beam / BGA / BGA_polar 44 | % BGA_polar needs lots of run time to rotate antenna polarization. (about 1.6 hr) 45 | %% Start 46 | NumPt_Rx = 21; 47 | Track_Rx = repmat(RxLoc,1,NumPt_Rx) + [0;0.1;0]*linspace(0,5,NumPt_Rx); 48 | TrackTheta_Rx = linspace(0,2*pi,NumPt_Rx); 49 | ShowIdxNeed = 2; % Y axis 50 | 51 | %%% The case of rotared receiver 52 | CoeffR_LOS_stack = zeros(1,NumPt_Rx); 53 | CoeffR_RIS_stack = zeros(1,NumPt_Rx); 54 | for Rx_idx = 1:NumPt_Rx 55 | AntData.rx.position = { Track_Rx(:, Rx_idx) }; 56 | disp([ 'Rx Location: ', num2str(Track_Rx(ShowIdxNeed, Rx_idx)) ]); 57 | RxRot_new = {[0, 0, TrackTheta_Rx(Rx_idx)/pi*180]}; 58 | RxRotNew = [RxRot, RxRot_new]; 59 | disp([ 'Rx Rotation: ', num2str(TrackTheta_Rx(Rx_idx)/pi*180) ]); 60 | % 61 | Coeff_LOS = GetCC_LOS( AntData, TxRot, RxRotNew ); 62 | Coeff_RIS = GetCC_RIS( Coeff_LOS, AntData, RISLoc, TxRot, RxRotNew, RISRot ); % Consider the controlling algorithm 63 | % 64 | CoeffR_LOS_stack(1,Rx_idx) = Coeff_LOS; 65 | CoeffR_RIS_stack(1,Rx_idx) = Coeff_RIS; 66 | end 67 | 68 | %% VNA 69 | CoeffR_stack = CoeffR_LOS_stack + CoeffR_RIS_stack; 70 | PowerR_dB = 10*log10(AntData.TxPower * (abs(CoeffR_stack).^2) / (1e-3)) - AntData.TxPower_dBm; 71 | 72 | %% Plot 73 | Track = Track_Rx(ShowIdxNeed,:); 74 | figure; 75 | PR = plot(Track, PowerR_dB, '--or','LineWidth',1.5); 76 | grid on; axis square; 77 | xlabel('Location of Rx on the y axis (m)'); 78 | ylabel('Loss (dB)'); 79 | legend([PR], 'Total loss with rotation'); 80 | axis([Track(1,1) Track(1,end) -60 -10]); 81 | set(gca,'XTick', Track(1,1):0.1:Track(1,end)); 82 | set(gca,'YTick', -60:10:-10); 83 | set(gca,'YTicklabel', {'60','50','40','30','20','10'}); 84 | -------------------------------------------------------------------------------- /RIS array/Main_RISarray_WithoutRotation.m: -------------------------------------------------------------------------------- 1 | % ========================================================================= 2 | % Article Title: 3 | % A Novel Channel Model for Reconfigurable Intelligent Surfaces 4 | % with Consideration of Polarization and Switch Impairments 5 | % (RIS array in Fig.12(a))(The case of receiver w/o rotation) 6 | % ------------------------------------------------------------------------- 7 | % Function: 8 | % CalculateCC.m / CalculateReflect.m / CalculateScatter.m / 9 | % ChangeGrid.m / LinearInterpolate.m / LinearInterpolateGrid.m / 10 | % LoadParameter.m / ArrayGenerate.m / 11 | % RodriguesRotVec.m / RotateAntenna.m / 12 | % ControlRIS_Perfectbeam.m / ControlRIS_DPSbeam.m / 13 | % ControlRIS_BGA.m / ControlRIS_BGApolar.m / 14 | % GetCC_LOS.m / GetCC_RIS.m 15 | % ------------------------------------------------------------------------- 16 | % Data: 17 | % Pattern file (AntH2.xlsx / AntH3.xlsx / AntH4.xlsx / 18 | % AntV2.xlsx / AntV3.xlsx / AntV4.xlsx) 19 | % ------------------------------------------------------------------------- 20 | % Copyright (c) 2023 De-Ming Chian and Chao-Kai Wen 21 | % E-mail: icefreeman123@gmail.com and chaokai.wen@mail.nsysu.edu.tw 22 | % Reference: QuaDriGa_2016.09.05_v1.4.8-571 23 | % ========================================================================= 24 | close all; clear all; clc 25 | %% Setup 26 | TxLoc = [ 0 ; 0 ; 0.8 ]; % Array center. Unit: m. 27 | RxLoc = [ 0 ; 0.2 ; 1.6 ]; % Array center. Unit: m. 28 | RISLoc = [ 0 ; 0 ; 0 ]; % Array center. Unit: m. 29 | AntData = LoadParameter( 'Pattern', TxLoc, RxLoc, RISLoc ); % Single antenna data 30 | 31 | TxRot = {[0, 90, 0], [0, 0, 90]}; % Rotate in order. Unit: degree 32 | RxRot = {[0, 90, 0], [0, 0, 90]}; % Rotate in order. Unit: degree 33 | RISRot = {[0, 90, 0], [180, 0, 0], [0, 0, -90]}; % Rotate in order. Unit: degree 34 | 35 | AntData.tx.size = [1, 1]; % Array size 36 | AntData.tx = ArrayGenerate( AntData, AntData.tx ); % Duplicate array data 37 | AntData.rx.size = [1, 1]; % Array size 38 | AntData.rx = ArrayGenerate( AntData, AntData.rx ); % Duplicate array data 39 | AntData.ris.size = [4, 4]; % Array size 40 | AntData.ris = ArrayGenerate( AntData, AntData.ris ); % Duplicate array data 41 | 42 | %%% Controlling algorithm: 43 | AntData.CtlMethod = 'Perfect_beam'; % Perfect_beam / DPS_beam / BGA 44 | 45 | %% Start 46 | NumPt_Rx = 21; 47 | Track_Rx = repmat(RxLoc,1,NumPt_Rx) + [0;0.1;0]*linspace(0,5,NumPt_Rx); 48 | TrackTheta_Rx = linspace(0,2*pi,NumPt_Rx); 49 | ShowIdxNeed = 2; % Y axis 50 | 51 | %%% The case of receiver w/o rotating 52 | Coeff_LOS_stack = zeros(1,NumPt_Rx); 53 | Coeff_RIS_stack = zeros(1,NumPt_Rx); 54 | for Rx_idx = 1:NumPt_Rx 55 | AntData.rx.position = { Track_Rx(:, Rx_idx) }; 56 | disp([ 'Rx Location: ', num2str(Track_Rx(ShowIdxNeed, Rx_idx)) ]); 57 | % 58 | Coeff_LOS = GetCC_LOS( AntData, TxRot, RxRot ); 59 | Coeff_RIS = GetCC_RIS( Coeff_LOS, AntData, RISLoc, TxRot, RxRot, RISRot ); % Consider the controlling algorithm 60 | % 61 | Coeff_LOS_stack(1,Rx_idx) = Coeff_LOS; 62 | Coeff_RIS_stack(1,Rx_idx) = Coeff_RIS; 63 | end 64 | 65 | %% VNA 66 | Coeff_stack = Coeff_LOS_stack + Coeff_RIS_stack; 67 | Power_dB = 10*log10(AntData.TxPower * (abs(Coeff_stack).^2) / (1e-3)) - AntData.TxPower_dBm; 68 | 69 | %% Plot 70 | Track = Track_Rx(ShowIdxNeed,:); 71 | figure; 72 | P = plot(Track, Power_dB, '-or','LineWidth',1.5); 73 | grid on; axis square; 74 | xlabel('Location of Rx on the y axis (m)'); 75 | ylabel('Loss (dB)'); 76 | legend([P],'Total loss'); 77 | axis([Track(1,1) Track(1,end) -90 -10]); 78 | set(gca,'XTick', Track(1,1):0.1:Track(1,end)); 79 | set(gca,'YTick', -90:10:-10); 80 | set(gca,'YTicklabel', {'90','80','70','60','50','40','30','20','10'}); 81 | -------------------------------------------------------------------------------- /RIS array/Pattern/AntH2.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS array/Pattern/AntH2.xlsx -------------------------------------------------------------------------------- /RIS array/Pattern/AntH3.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS array/Pattern/AntH3.xlsx -------------------------------------------------------------------------------- /RIS array/Pattern/AntH4.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS array/Pattern/AntH4.xlsx -------------------------------------------------------------------------------- /RIS array/Pattern/AntV2.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS array/Pattern/AntV2.xlsx -------------------------------------------------------------------------------- /RIS array/Pattern/AntV3.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS array/Pattern/AntV3.xlsx -------------------------------------------------------------------------------- /RIS array/Pattern/AntV4.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS array/Pattern/AntV4.xlsx -------------------------------------------------------------------------------- /RIS array/RodriguesRotVec.m: -------------------------------------------------------------------------------- 1 | function [ AllPtAndCenter_new ] = RodriguesRotVec( OrgVec, RotVec, Pt ) 2 | %% Rodrigues' rotation formula 3 | RotAng = acos( dot(OrgVec, RotVec) / (norm(OrgVec)*norm(RotVec)) ); % rotation angle 4 | RotAxis = cross(OrgVec, RotVec); % rotation axis 5 | RotAxis = RotAxis / norm(RotAxis); 6 | Kmat = [0, -1*RotAxis(3), RotAxis(2); ... 7 | RotAxis(3), 0, -1*RotAxis(1); ... 8 | -1*RotAxis(2), RotAxis(1), 0]; % cross-product matrix 9 | Rmat = eye(3) + sin(RotAng)*Kmat + (1-cos(RotAng))*Kmat*Kmat; % rotation matrix 10 | AllPtAndCenter_new = Rmat * Pt; % rotated vector 11 | 12 | end 13 | 14 | -------------------------------------------------------------------------------- /RIS array/RotateAntenna.m: -------------------------------------------------------------------------------- 1 | function [ AntData ] = RotateAntenna( AntData, rot_angle, AntIdx ) 2 | %% Setup 3 | no_ant = AntData.no_ant; 4 | 5 | % Get the angles. 6 | phi = AntData.azimuth_grid; 7 | theta = AntData.elevation_grid'; 8 | no_az = AntData.no_az; 9 | no_el = AntData.no_el; 10 | 11 | % Change the unit from degree to rad. 12 | rot_angle = rot_angle/180*pi; 13 | 14 | %% Rotation matrix 15 | % Calculate the rotation matrix. 16 | rx = rot_angle(1); 17 | ry = rot_angle(2); 18 | rz = rot_angle(3); 19 | rot = zeros(3,3); 20 | rot(1,1) = cos(rz) * cos(ry); 21 | rot(2,1) = sin(rz) * cos(ry); 22 | rot(3,1) = -1 * sin(ry); 23 | rot(1,2) = cos(rz) * sin(ry) * sin(rx) - sin(rz) * cos(rx); 24 | rot(2,2) = sin(rz) * sin(ry) * sin(rx) + cos(rz) * cos(rx); 25 | rot(3,2) = cos(ry) * sin(rx); 26 | rot(1,3) = cos(rz) * sin(ry) * cos(rx) + sin(rz) * sin(rx); 27 | rot(2,3) = sin(rz) * sin(ry) * cos(rx) - cos(rz) * sin(rx); 28 | rot(3,3) = cos(ry) * cos(rx); 29 | 30 | %%% Check: rot2 = rot. 31 | % Rx = makehgtform('xrotate', rx); 32 | % rotx = Rx(1:3, 1:3); 33 | % Ry = makehgtform('yrotate', ry); 34 | % roty = Ry(1:3, 1:3); 35 | % Rz = makehgtform('zrotate', rz); 36 | % rotz = Rz(1:3, 1:3); 37 | % rot2 = rotz * roty * rotx; 38 | 39 | %% Theta and Phi of signal direction in the global and local coordinate system 40 | % Change Theta from [0, pi] to [pi/2, -pi/2]. 41 | theta_mat = repmat(theta, [1, length(phi)]); 42 | theta_mat = -1*theta_mat + pi/2; 43 | % Change Phi from [0, 2*pi] to [pi, -pi]. 44 | phiTMP = phi; 45 | phiTMP_idx = phiTMP >= pi; %%% 46 | phiTMP(phiTMP_idx) = phiTMP(phiTMP_idx) - 2*pi; 47 | phi_mat = repmat(phiTMP, [length(theta), 1]); 48 | % Transform from spherical coordinates into Cartesian coordinates. 49 | [ Fx, Fy, Fz ] = sph2cart(phi_mat, theta_mat, 1e10); 50 | 51 | % Rotation of signal direction 52 | Fx_r = rot(1,1)*Fx + rot(2,1)*Fy +rot(3,1)*Fz; % Transpose 53 | Fy_r = rot(1,2)*Fx + rot(2,2)*Fy +rot(3,2)*Fz; 54 | Fz_r = rot(1,3)*Fx + rot(2,3)*Fy +rot(3,3)*Fz; 55 | 56 | % Transforme from Cartesian coordinates into spherical coordinates. 57 | [phi_mat_new, theta_mat_new] = cart2sph( Fx_r, Fy_r, Fz_r ); % [pi, -pi] and [pi/2, -pi/2]. 58 | % The pattern is not defined when the theta > 90 degree and < -90 degree. 59 | err_limit = 1e-5; 60 | theta_out_idx = theta_mat_new < -pi/2 + err_limit; 61 | theta_mat_new(theta_out_idx) = -pi/2 + err_limit; 62 | theta_out_idx = theta_mat_new > pi/2 - err_limit; 63 | theta_mat_new(theta_out_idx) = pi/2 - err_limit; 64 | % Change Theta from [pi/2, -pi/2] to [0, pi]. 65 | theta_mat_new = -1*theta_mat_new + pi/2; 66 | % Change Phi from [pi, -pi] to [0, 2*pi]. 67 | phi_mat_new_pi_idx = phi_mat_new < 0; 68 | phi_mat_new(phi_mat_new_pi_idx) = phi_mat_new(phi_mat_new_pi_idx) + 2*pi; 69 | 70 | %% Transformation matrix 71 | % Global coordinate system in theta direction. 72 | T_theta2x_g = cos(theta) * cos(phi); 73 | T_theta2y_g = cos(theta) * sin(phi); 74 | T_theta2z_g = -1 * sin(theta) * ones(1,no_az); 75 | 76 | % Global coordinate system in phi direction. 77 | T_phi2x_g = ones(no_el,1) * -1 * sin(phi); 78 | T_phi2y_g = ones(no_el,1) * cos(phi); 79 | T_phi2z_g = zeros( no_el , no_az ); 80 | 81 | % Local coordinate system in theta direction. 82 | T_theta2x_l = cos(theta_mat_new) .* cos(phi_mat_new); 83 | T_theta2y_l = cos(theta_mat_new) .* sin(phi_mat_new); 84 | T_theta2z_l = -1 * sin(theta_mat_new); 85 | 86 | % Local coordinate system in phi direction. 87 | T_phi2x_l = -1 * sin(phi_mat_new); 88 | T_phi2y_l = cos(phi_mat_new); 89 | T_phi2z_l = zeros( no_el , no_az ); 90 | 91 | %% Polarization rotation matrix 92 | T_theta2x_tmp = rot(1,1)*T_theta2x_l + rot(1,2)*T_theta2y_l + rot(1,3)*T_theta2z_l; 93 | T_theta2y_tmp = rot(2,1)*T_theta2x_l + rot(2,2)*T_theta2y_l + rot(2,3)*T_theta2z_l; 94 | T_theta2z_tmp = rot(3,1)*T_theta2x_l + rot(3,2)*T_theta2y_l + rot(3,3)*T_theta2z_l; 95 | T_phi2x_tmp = rot(1,1)*T_phi2x_l + rot(1,2)*T_phi2y_l + rot(1,3)*T_phi2z_l; 96 | T_phi2y_tmp = rot(2,1)*T_phi2x_l + rot(2,2)*T_phi2y_l + rot(2,3)*T_phi2z_l; 97 | T_phi2z_tmp = rot(3,1)*T_phi2x_l + rot(3,2)*T_phi2y_l + rot(3,3)*T_phi2z_l; 98 | Mo_11 = T_theta2x_tmp.*T_theta2x_g + T_theta2y_tmp.*T_theta2y_g + T_theta2z_tmp.*T_theta2z_g; 99 | Mo_12 = T_phi2x_tmp.*T_theta2x_g + T_phi2y_tmp.*T_theta2y_g + T_phi2z_tmp.*T_theta2z_g; 100 | % Mo_21 = T_theta2x_tmp.*T_phi2x_g + T_theta2y_tmp.*T_phi2y_g + T_theta2z_tmp.*T_phi2z_g; 101 | % Mo_22 = T_phi2x_tmp.*T_phi2x_g + T_phi2y_tmp.*T_phi2y_g + T_phi2z_tmp.*T_phi2z_g; 102 | 103 | %%% Check: Mo_11 = Mo_22; Mo_12 = -1*Mo_21; 104 | Mo_21 = -1*Mo_12; 105 | Mo_22 = Mo_11; 106 | 107 | %% Reading the original pattern at the rotated signal direction 108 | [ V_org, H_org, T_org ] = LinearInterpolateGrid( AntData , phi_mat_new , theta_mat_new ); 109 | 110 | %% Transformation of the polarization 111 | Vtmp = V_org(:); 112 | Htmp = H_org(:); 113 | Ttmp = T_org(:); 114 | Vcell = cell(no_ant,1); 115 | Hcell = cell(no_ant,1); 116 | Tcell = cell(no_ant,1); 117 | if exist('AntIdx') % Assigned antenna needed to be rotated 118 | Vcell = Vtmp; 119 | Hcell = Htmp; 120 | Tcell = Ttmp; 121 | Vtmp_i = Vtmp{AntIdx}; 122 | Htmp_i = Htmp{AntIdx}; 123 | V_new = Mo_11.*Vtmp_i + Mo_12.*Htmp_i; 124 | H_new = Mo_21.*Vtmp_i + Mo_22.*Htmp_i; 125 | T_new = sqrt(V_new.^2 + H_new.^2); 126 | Vcell(AntIdx) = {V_new}; 127 | Hcell(AntIdx) = {H_new}; 128 | Tcell(AntIdx) = {T_new}; 129 | else % All antenna needed to be rotated 130 | for i = 1:no_ant 131 | Vtmp_i = Vtmp{i}; 132 | Htmp_i = Htmp{i}; 133 | V_new = Mo_11.*Vtmp_i + Mo_12.*Htmp_i; 134 | H_new = Mo_21.*Vtmp_i + Mo_22.*Htmp_i; 135 | T_new = sqrt(V_new.^2 + H_new.^2); 136 | Vcell(i) = {V_new}; 137 | Hcell(i) = {H_new}; 138 | Tcell(i) = {T_new}; 139 | end 140 | end 141 | Vcell = reshape(Vcell, size(V_org)); 142 | Hcell = reshape(Hcell, size(H_org)); 143 | Tcell = reshape(Tcell, size(T_org)); 144 | 145 | %% Rotation of Orientation 146 | orient_org = AntData.orient; 147 | Ox = orient_org(1,1); 148 | Oy = orient_org(2,1); 149 | Oz = orient_org(3,1); 150 | Ox_n = rot(1,1)*Ox + rot(1,2)*Oy +rot(1,3)*Oz; 151 | Oy_n = rot(2,1)*Ox + rot(2,2)*Oy +rot(2,3)*Oz; 152 | Oz_n = rot(3,1)*Ox + rot(3,2)*Oy +rot(3,3)*Oz; 153 | orient_new = [Ox_n;Oy_n;Oz_n]; 154 | AntData.orient = orient_new; 155 | 156 | %% Output 157 | AntData.V = Vcell; 158 | AntData.H = Hcell; 159 | AntData.T = Tcell; 160 | end 161 | 162 | -------------------------------------------------------------------------------- /RIS element/CalculateCC.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS element/CalculateCC.m -------------------------------------------------------------------------------- /RIS element/CalculateReflect.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS element/CalculateReflect.m -------------------------------------------------------------------------------- /RIS element/CalculateScatter.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS element/CalculateScatter.m -------------------------------------------------------------------------------- /RIS element/ChangeGrid.m: -------------------------------------------------------------------------------- 1 | function AntData = ChangeGrid( AntData , Azi_grid , Ele_grid ) 2 | %% Set grid 3 | Ele = repmat( Ele_grid' , 1 , numel(Azi_grid) ); 4 | Azi = repmat( Azi_grid , numel(Ele_grid) , 1 ); 5 | EleIDX = Ele_grid <= max(AntData.elevation_grid) & Ele_grid >= min(AntData.elevation_grid); 6 | AziIDX = Azi_grid <= max(AntData.azimuth_grid) & Azi_grid >= min(AntData.azimuth_grid); 7 | [V, H] = LinearInterpolate( AntData , Azi(EleIDX,AziIDX) , Ele(EleIDX,AziIDX) ); 8 | %% Output 9 | AntData.elevation_grid = Ele_grid(EleIDX); 10 | AntData.azimuth_grid = Azi_grid(AziIDX); 11 | AntData.V = V; 12 | AntData.H = H; 13 | AntData.T = sqrt(V.^2 + H.^2); 14 | AntData.no_el = length(AntData.elevation_grid); 15 | AntData.no_az = length(AntData.azimuth_grid); 16 | end 17 | -------------------------------------------------------------------------------- /RIS element/LinearInterpolate.m: -------------------------------------------------------------------------------- 1 | function [ V, H ] = LinearInterpolate( AntData, azimuth_meshgrid_new, elevation_meshgrid_new ) 2 | %% Linear Interpolation 3 | azimuth_grid = AntData.azimuth_grid; 4 | elevation_grid = AntData.elevation_grid; 5 | azimuth_meshgrid = repmat(azimuth_grid, [length(elevation_grid),1]); 6 | elevation_meshgrid = repmat(elevation_grid.', [1,length(azimuth_grid)]); 7 | V = AntData.V; 8 | H = AntData.H; 9 | V_new = interp2(azimuth_meshgrid, elevation_meshgrid, V, azimuth_meshgrid_new, elevation_meshgrid_new, 'linear'); 10 | V_new(:,end) = V_new(:,1); 11 | H_new = interp2(azimuth_meshgrid, elevation_meshgrid, H, azimuth_meshgrid_new, elevation_meshgrid_new, 'linear'); 12 | H_new(:,end) = H_new(:,1); 13 | %% Output 14 | V = V_new; 15 | H = H_new; 16 | end 17 | 18 | -------------------------------------------------------------------------------- /RIS element/LoadParameter.m: -------------------------------------------------------------------------------- 1 | function [ AntData ] = LoadParameter( file, TxLoc, RxLoc, RISLoc ) 2 | %% Setup 3 | TxPower_dBm = 0; % unit: dBm. 4 | AntData.TxPower_dBm = TxPower_dBm; 5 | AntData.TxPower = 1e-3 * 10^(TxPower_dBm/10); % unit: W. 6 | AntData.LossType = 'withloss'; % 'withloss' / 'noloss' 7 | AntData.freq = 3.5e9; % Center Frequency (unit: Hz) 8 | 9 | elevation_range = [0, pi]; 10 | azimuth_range = [0, 2*pi]; 11 | AntData.elevation_range = elevation_range; 12 | AntData.azimuth_range = azimuth_range; 13 | 14 | if exist('RISLoc','var') 15 | AntNum = 3; 16 | else 17 | AntNum = 2; 18 | end 19 | %% Load radiation pattern 20 | startIDX = 2; 21 | path_now = pwd; 22 | path_data = [path_now,'\', file]; 23 | cd([path_data]); 24 | listDateTMP = dir; 25 | listDate = cell((length(listDateTMP)-2), 2); 26 | for i=1:size(listDate,1) 27 | listDate(i,1) = {listDateTMP(i+2).name}; 28 | end 29 | for i=1:size(listDate,1) 30 | filename = listDate{i,1}; 31 | ANTcsvTMP = xlsread([filename]); 32 | ANTcsv = ANTcsvTMP(startIDX:end , startIDX:end); 33 | listDate(i,2) = {ANTcsv}; clear ANTcsv 34 | end 35 | cd([path_now]); 36 | 37 | %% 38 | typeAll = {'tx','rx','ris'}; 39 | AntNeedAll = [1, 3, 2]; 40 | 41 | for i = 1:AntNum 42 | type = typeAll{1,i}; 43 | AntNeed = AntNeedAll(1,i); 44 | 45 | CustAntV = listDate(AntNeed + (size(listDate,1)/2),:); 46 | CustAntH = listDate(AntNeed,:); 47 | Vtmp = CustAntV{1,2}; 48 | Htmp = CustAntH{1,2}; 49 | Vtmp = sqrt(10.^(Vtmp/10)); 50 | Htmp = sqrt(10.^(Htmp/10)); 51 | no_elNeed = size(Vtmp, 1); 52 | no_azNeed = size(Vtmp, 2); 53 | elevation_gridNeed = linspace(elevation_range(1), elevation_range(2), no_elNeed); 54 | azimuth_gridNeed = linspace(azimuth_range(1), azimuth_range(2), no_azNeed); 55 | 56 | switch type 57 | case 'tx' 58 | AntData.tx.name = 'patch'; 59 | AntData.tx.V = Vtmp; 60 | AntData.tx.H = Htmp; 61 | AntData.tx.T = sqrt(Vtmp.^2 + Htmp.^2); 62 | AntData.tx.no_el = no_elNeed; 63 | AntData.tx.no_az = no_azNeed; 64 | AntData.tx.elevation_grid = elevation_gridNeed; 65 | AntData.tx.azimuth_grid = azimuth_gridNeed; 66 | AntData.tx.position = TxLoc; 67 | case 'rx' 68 | AntData.rx.name = 'patch'; 69 | AntData.rx.V = Vtmp; 70 | AntData.rx.H = Htmp; 71 | AntData.rx.T = sqrt(Vtmp.^2 + Htmp.^2); 72 | AntData.rx.no_el = no_elNeed; 73 | AntData.rx.no_az = no_azNeed; 74 | AntData.rx.elevation_grid = elevation_gridNeed; 75 | AntData.rx.azimuth_grid = azimuth_gridNeed; 76 | AntData.rx.position = RxLoc; 77 | case 'ris' 78 | AntData.ris.name = 'patch'; 79 | AntData.ris.V = Vtmp; 80 | AntData.ris.H = Htmp; 81 | AntData.ris.T = sqrt(Vtmp.^2 + Htmp.^2); 82 | AntData.ris.no_el = no_elNeed; 83 | AntData.ris.no_az = no_azNeed; 84 | AntData.ris.elevation_grid = elevation_gridNeed; 85 | AntData.ris.azimuth_grid = azimuth_gridNeed; 86 | AntData.ris.position = RISLoc; 87 | AntData.ris.area_a = 0.094; % unit: m. 88 | AntData.ris.area_b = 0.073; 89 | AntData.ris.normal = [0;0;1]; % Normal vector of RIS 90 | AntData.ris.InjEff = 1; 91 | end 92 | end 93 | 94 | end 95 | 96 | -------------------------------------------------------------------------------- /RIS element/Main.m: -------------------------------------------------------------------------------- 1 | % ========================================================================= 2 | % Article Title: 3 | % A Novel Channel Model for Reconfigurable Intelligent Surfaces 4 | % with Consideration of Polarization and Switch Impairments 5 | % (RIS element in Fig.7(c)) 6 | % ------------------------------------------------------------------------- 7 | % Function: 8 | % CalculateCC.m / CalculateReflect.m / CalculateScatter.m / 9 | % ChangeGrid.m / LinearInterpolate.m / 10 | % LoadParameter.m / RotateAntenna.m 11 | % ------------------------------------------------------------------------- 12 | % Data: 13 | % Pattern file (AntH2.xlsx / AntH3.xlsx / AntH4.xlsx / 14 | % AntV2.xlsx / AntV3.xlsx / AntV4.xlsx) 15 | % ------------------------------------------------------------------------- 16 | % Copyright (c) 2023 De-Ming Chian and Chao-Kai Wen 17 | % E-mail: icefreeman123@gmail.com and chaokai.wen@mail.nsysu.edu.tw 18 | % Reference: QuaDriGa_2016.09.05_v1.4.8-571 19 | % ========================================================================= 20 | close all; clear all; clc 21 | %% Set up location & Load antenna gain 22 | TxLoc = [ 0 ; -0.1 ; 0.1 ]; % unit: m 23 | RxLoc = [ 0 ; 0.1 ; 0.1 ]; 24 | RISLoc = [ 0 ; 0 ; 0 ]; 25 | AntData = LoadParameter( 'Pattern', TxLoc, RxLoc, RISLoc ); 26 | 27 | %% Digital Phase Shifter (DPS) 28 | DPS_phase = [-33.64, -61.63, -102.0, -142.1, ... 29 | -178.0, -225.7, -311.1, -365.5, ... 30 | -395.4, -423.8, -462.1, -508.4, ... 31 | -545.1, -596.2, -681.1, -733.9]; 32 | DPS_loss = [3.601, 3.516, 5.175, 7.309, ... 33 | 6.442, 7.578, 8.294, 6.973, ... 34 | 3.289, 3.336, 5.031, 7.238, ... 35 | 6.305, 7.194, 7.500, 6.228]; 36 | DPS_phase(DPS_phase<-360) = DPS_phase(DPS_phase<-360) + 360; 37 | DPS_phase(DPS_phase<-360) = DPS_phase(DPS_phase<-360) + 360; 38 | DPS_phase = DPS_phase/180*pi; 39 | DPS_need = sqrt(10.^(-0.1*DPS_loss)) .* exp(1j*DPS_phase + 1j*(2*pi)*5/12); 40 | 41 | %% Grid 42 | ele = AntData.elevation_range; 43 | azi = AntData.azimuth_range; 44 | % Change grid with interpolate (Rough) 45 | elevation_grid = ele(1):(10/180*pi):ele(2); 46 | azimuth_grid = azi(1):(10/180*pi):azi(2); 47 | AntData.tx = ChangeGrid( AntData.tx , azimuth_grid , elevation_grid ); 48 | AntData.rx = ChangeGrid( AntData.rx , azimuth_grid , elevation_grid ); 49 | AntData.ris = ChangeGrid( AntData.ris , azimuth_grid , elevation_grid ); 50 | % Change grid with interpolate (Need) 51 | elevation_grid = ele(1):(1/180*pi):ele(2); 52 | azimuth_grid = azi(1):(1/180*pi):azi(2); 53 | AntData.tx = ChangeGrid( AntData.tx , azimuth_grid , elevation_grid ); 54 | AntData.rx = ChangeGrid( AntData.rx , azimuth_grid , elevation_grid ); 55 | AntData.ris = ChangeGrid( AntData.ris , azimuth_grid , elevation_grid ); 56 | 57 | %% Rotate pattern 58 | % Rotate in order. unit: degree 59 | TxRot = {[0, 90, 0], [0, 0, 90]}; 60 | RxRot = {[0, 90, 0], [0, 0, 90]}; 61 | RISRot_Rot0 = {[0, 90, 0], [180, 0, 0], [0, 0, 90]}; % Case 1 (without rotation) 62 | RISRot_Rot90 = {[0, 90, 0], [180, 0, 0], [0, 0, 90], [0, 0, 90]}; % Case 2 (rotate 90 deg.) 63 | TxRotIDX_num = length(TxRot); 64 | for i = 1:TxRotIDX_num 65 | TxRotNeed = TxRot{i}; 66 | AntData.tx = RotateAntenna( AntData.tx, TxRotNeed ); 67 | end 68 | RxRotIDX_num = length(RxRot); 69 | for i = 1:RxRotIDX_num 70 | RxRotNeed = RxRot{i}; 71 | AntData.rx = RotateAntenna( AntData.rx, RxRotNeed ); 72 | end 73 | AntData_Rot0 = AntData; 74 | AntData_Rot90 = AntData; 75 | RISRotIDX_num = length(RISRot_Rot0); 76 | for i = 1:RISRotIDX_num 77 | RISRotNeed = RISRot_Rot0{i}; 78 | AntData_Rot0.ris = RotateAntenna( AntData_Rot0.ris, RISRotNeed ); 79 | end 80 | RISRotIDX_num = length(RISRot_Rot90); 81 | for i = 1:RISRotIDX_num 82 | RISRotNeed = RISRot_Rot90{i}; 83 | AntData_Rot90.ris = RotateAntenna( AntData_Rot90.ris, RISRotNeed ); 84 | end 85 | 86 | %% Move (Y axis) 87 | Dstack_Open_Rot0 = zeros(1, length(DPS_need)); 88 | Dstack_Open_Rot90 = zeros(1, length(DPS_need)); 89 | for j = 1:length(DPS_need) 90 | % Antenna position 91 | AntData_Rot0.tx.position = [ 0 ; -0.1 ; 0.25 ]; 92 | AntData_Rot0.rx.position = [ 0 ; 0.1 ; 0.25 ]; 93 | AntData_Rot90.tx.position = [ 0 ; -0.1 ; 0.25 ]; 94 | AntData_Rot90.rx.position = [ 0 ; 0.1 ; 0.25 ]; 95 | 96 | % Calculate LOS channel coefficient 97 | [ Coeff_Tx2Rx_Rot0, ~ ] = CalculateCC( AntData_Rot0, AntData_Rot0.tx, AntData_Rot0.rx ); 98 | [ Coeff_Tx2Rx_Rot90, ~ ] = CalculateCC( AntData_Rot90, AntData_Rot90.tx, AntData_Rot90.rx ); 99 | 100 | % Calculate RIS channel coefficient 101 | DPS = DPS_need(j); 102 | [ Coeff_Tx2RIS_Rot0, ~ ] = CalculateCC( AntData_Rot0, AntData_Rot0.tx, AntData_Rot0.ris ); 103 | [ Coeff_RIS2Rx_Rot0, ~ ] = CalculateCC( AntData_Rot0, AntData_Rot0.ris, AntData_Rot0.rx ); 104 | Coeff_Tx2RIS2Rx_Rot0 = Coeff_Tx2RIS_Rot0 * Coeff_RIS2Rx_Rot0 * DPS; 105 | [ Coeff_Tx2RIS_Rot90, ~ ] = CalculateCC( AntData_Rot90, AntData_Rot90.tx, AntData_Rot90.ris ); 106 | [ Coeff_RIS2Rx_Rot90, ~ ] = CalculateCC( AntData_Rot90, AntData_Rot90.ris, AntData_Rot90.rx ); 107 | Coeff_Tx2RIS2Rx_Rot90 = Coeff_Tx2RIS_Rot90 * Coeff_RIS2Rx_Rot90 * DPS; 108 | 109 | % Calculate Scatter coefficient on RIS 110 | [ Coeff_scatter_Rot0, ~ ] = CalculateScatter( AntData_Rot0 ); 111 | [ Coeff_scatter_Rot90, ~ ] = CalculateScatter( AntData_Rot90 ); 112 | 113 | % Calculate Reflection coefficient on RIS 114 | [ Coeff_reflect_Rot0, ~ ] = CalculateReflect( AntData_Rot0); 115 | [ Coeff_reflect_Rot90, ~ ] = CalculateReflect( AntData_Rot90); 116 | 117 | % Combine coefficient (Channel coefficient) 118 | Coeff_Open_Rot0 = Coeff_Tx2Rx_Rot0 + Coeff_reflect_Rot0 + Coeff_scatter_Rot0 + Coeff_Tx2RIS2Rx_Rot0; 119 | Coeff_Open_Rot90 = Coeff_Tx2Rx_Rot90 + Coeff_reflect_Rot90 + Coeff_scatter_Rot90 + Coeff_Tx2RIS2Rx_Rot90; 120 | 121 | % Stack data 122 | Dstack_Open_Rot0(1,j) = Coeff_Open_Rot0; 123 | Dstack_Open_Rot90(1,j) = Coeff_Open_Rot90; 124 | end 125 | 126 | %% Results 127 | % Power Ratio 128 | Power_stack = AntData.TxPower * (abs(Dstack_Open_Rot0).^2); 129 | Power_stack_dBm = 10*log10(Power_stack / (1e-3)); % unit: dBm 130 | Power_ratio_dB = Power_stack_dBm - AntData.TxPower_dBm; % Corresponding to the meas. of VNA 131 | Power_ratio_dB_Open_Rot0 = Power_ratio_dB; 132 | Power_stack = AntData.TxPower * (abs(Dstack_Open_Rot90).^2); 133 | Power_stack_dBm = 10*log10(Power_stack / (1e-3)); % unit: dBm 134 | Power_ratio_dB = Power_stack_dBm - AntData.TxPower_dBm; % Corresponding to the meas. of VNA 135 | Power_ratio_dB_Open_Rot90 = Power_ratio_dB; 136 | 137 | % Measured results 138 | VNA_dB_Open_Rot0 = [-31.46 ; -30.53 ; -29.30 ; -28.68 ; ... 139 | -29.16 ; -30.31 ; -30.80 ; -31.96 ; ... 140 | -31.26 ; -29.57 ; -28.73 ; -28.85 ; ... 141 | -29.47 ; -29.39 ; -31.12 ; -31.77]; % Case 1 by VNA 142 | VNA_dB_Open_Rot90 = [-30.33 ; -30.12 ; -30.21 ; -29.94 ; ... 143 | -30.07 ; -30.24 ; -30.08 ; -30.14 ; ... 144 | -30.23 ; -30.10 ; -30.49 ; -29.77 ; ... 145 | -30.19 ; -30.94 ; -30.47 ; -30.20]; % Case 2 by VNA 146 | 147 | % Plot results 148 | DPSstate_idx = 1:length(DPS_need); 149 | figure; 150 | a = plot(DPSstate_idx, Power_ratio_dB_Open_Rot0,'r-','LineWidth',1.5); hold on; 151 | b = plot(DPSstate_idx, VNA_dB_Open_Rot0,'r--s','LineWidth',1.5,'MarkerSize',8); 152 | c = plot(DPSstate_idx, Power_ratio_dB_Open_Rot90,'b-','LineWidth',1.5); 153 | d = plot(DPSstate_idx, VNA_dB_Open_Rot90,'b--x','LineWidth',1.5,'MarkerSize',8); 154 | hold off; grid on; axis square; 155 | title('RIS element for the different polarization direction'); 156 | xlabel('DPS state'); 157 | ylabel('Loss (dB)'); 158 | legend([a,b,c,d], 'Rot. 0 deg / Sim.','Rot. 0 deg / Meas.', 'Rot. 90 deg / Sim.','Rot. 90 deg / Meas.'); 159 | axis([DPSstate_idx(1) DPSstate_idx(end) -40 -20]); 160 | set(gca,'XTick', DPSstate_idx(1,1):3:DPSstate_idx(1,end)); 161 | set(gca,'YTick', -40:5:-20); 162 | set(gca,'YTicklabel', {'40','35','30','25','20'}); 163 | 164 | -------------------------------------------------------------------------------- /RIS element/Pattern/AntH2.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS element/Pattern/AntH2.xlsx -------------------------------------------------------------------------------- /RIS element/Pattern/AntH3.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS element/Pattern/AntH3.xlsx -------------------------------------------------------------------------------- /RIS element/Pattern/AntH4.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS element/Pattern/AntH4.xlsx -------------------------------------------------------------------------------- /RIS element/Pattern/AntV2.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS element/Pattern/AntV2.xlsx -------------------------------------------------------------------------------- /RIS element/Pattern/AntV3.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS element/Pattern/AntV3.xlsx -------------------------------------------------------------------------------- /RIS element/Pattern/AntV4.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icefreeman123/MatlabChannelModelForRIS/f000cb69d6bb13bf6b80d65fd532008afa574d60/RIS element/Pattern/AntV4.xlsx -------------------------------------------------------------------------------- /RIS element/RotateAntenna.m: -------------------------------------------------------------------------------- 1 | function [ AntData ] = RotateAntenna( AntData, rot_angle ) 2 | %% Setup 3 | % Get the angles. 4 | phi = AntData.azimuth_grid; 5 | theta = AntData.elevation_grid'; 6 | no_az = AntData.no_az; 7 | no_el = AntData.no_el; 8 | 9 | % Change the unit from degree to rad. 10 | rot_angle = rot_angle/180*pi; 11 | 12 | %% Rotation matrix 13 | % Calculate the rotation matrix. 14 | rx = rot_angle(1); 15 | ry = rot_angle(2); 16 | rz = rot_angle(3); 17 | rot = zeros(3,3); 18 | rot(1,1) = cos(rz) * cos(ry); 19 | rot(2,1) = sin(rz) * cos(ry); 20 | rot(3,1) = -1 * sin(ry); 21 | rot(1,2) = cos(rz) * sin(ry) * sin(rx) - sin(rz) * cos(rx); 22 | rot(2,2) = sin(rz) * sin(ry) * sin(rx) + cos(rz) * cos(rx); 23 | rot(3,2) = cos(ry) * sin(rx); 24 | rot(1,3) = cos(rz) * sin(ry) * cos(rx) + sin(rz) * sin(rx); 25 | rot(2,3) = sin(rz) * sin(ry) * cos(rx) - cos(rz) * sin(rx); 26 | rot(3,3) = cos(ry) * cos(rx); 27 | 28 | %% Theta and Phi of signal direction in the global and local coordinate system 29 | % Change Theta from [0, pi] to [pi/2, -pi/2]. 30 | theta_mat = repmat(theta, [1, length(phi)]); 31 | theta_mat = -1*theta_mat + pi/2; 32 | % Change Phi from [0, 2*pi] to [pi, -pi]. 33 | phiTMP = phi; 34 | phiTMP_idx = phiTMP >= pi; %%% 35 | phiTMP(phiTMP_idx) = phiTMP(phiTMP_idx) - 2*pi; 36 | phi_mat = repmat(phiTMP, [length(theta), 1]); 37 | % Transform from spherical coordinates into Cartesian coordinates. 38 | [ Fx, Fy, Fz ] = sph2cart(phi_mat, theta_mat, 1e10); 39 | 40 | % Rotation of signal direction 41 | Fx_r = rot(1,1)*Fx + rot(2,1)*Fy +rot(3,1)*Fz; % Transpose 42 | Fy_r = rot(1,2)*Fx + rot(2,2)*Fy +rot(3,2)*Fz; 43 | Fz_r = rot(1,3)*Fx + rot(2,3)*Fy +rot(3,3)*Fz; 44 | 45 | % Transforme from Cartesian coordinates into spherical coordinates. 46 | [phi_mat_new, theta_mat_new] = cart2sph( Fx_r, Fy_r, Fz_r ); % [pi, -pi] and [pi/2, -pi/2]. 47 | % The pattern is not defined when the theta > 90 degree and < -90 degree. 48 | err_limit = 1e-5; 49 | theta_out_idx = theta_mat_new < -pi/2 + err_limit; 50 | theta_mat_new(theta_out_idx) = -pi/2 + err_limit; 51 | theta_out_idx = theta_mat_new > pi/2 - err_limit; 52 | theta_mat_new(theta_out_idx) = pi/2 - err_limit; 53 | % Change Theta from [pi/2, -pi/2] to [0, pi]. 54 | theta_mat_new = -1*theta_mat_new + pi/2; 55 | % Change Phi from [pi, -pi] to [0, 2*pi]. 56 | phi_mat_new_pi_idx = phi_mat_new < 0; 57 | phi_mat_new(phi_mat_new_pi_idx) = phi_mat_new(phi_mat_new_pi_idx) + 2*pi; 58 | 59 | %% Transformation matrix 60 | % Global coordinate system in theta direction. 61 | T_theta2x_g = cos(theta) * cos(phi); 62 | T_theta2y_g = cos(theta) * sin(phi); 63 | T_theta2z_g = -1 * sin(theta) * ones(1,no_az); 64 | 65 | % Global coordinate system in phi direction. 66 | T_phi2x_g = ones(no_el,1) * -1 * sin(phi); 67 | T_phi2y_g = ones(no_el,1) * cos(phi); 68 | T_phi2z_g = zeros( no_el , no_az ); 69 | 70 | % Local coordinate system in theta direction. 71 | T_theta2x_l = cos(theta_mat_new) .* cos(phi_mat_new); 72 | T_theta2y_l = cos(theta_mat_new) .* sin(phi_mat_new); 73 | T_theta2z_l = -1 * sin(theta_mat_new); 74 | 75 | % Local coordinate system in phi direction. 76 | T_phi2x_l = -1 * sin(phi_mat_new); 77 | T_phi2y_l = cos(phi_mat_new); 78 | T_phi2z_l = zeros( no_el , no_az ); 79 | 80 | %% Polarization rotation matrix 81 | T_theta2x_tmp = rot(1,1)*T_theta2x_l + rot(1,2)*T_theta2y_l + rot(1,3)*T_theta2z_l; 82 | T_theta2y_tmp = rot(2,1)*T_theta2x_l + rot(2,2)*T_theta2y_l + rot(2,3)*T_theta2z_l; 83 | T_theta2z_tmp = rot(3,1)*T_theta2x_l + rot(3,2)*T_theta2y_l + rot(3,3)*T_theta2z_l; 84 | T_phi2x_tmp = rot(1,1)*T_phi2x_l + rot(1,2)*T_phi2y_l + rot(1,3)*T_phi2z_l; 85 | T_phi2y_tmp = rot(2,1)*T_phi2x_l + rot(2,2)*T_phi2y_l + rot(2,3)*T_phi2z_l; 86 | T_phi2z_tmp = rot(3,1)*T_phi2x_l + rot(3,2)*T_phi2y_l + rot(3,3)*T_phi2z_l; 87 | Mo_11 = T_theta2x_tmp.*T_theta2x_g + T_theta2y_tmp.*T_theta2y_g + T_theta2z_tmp.*T_theta2z_g; 88 | Mo_12 = T_phi2x_tmp.*T_theta2x_g + T_phi2y_tmp.*T_theta2y_g + T_phi2z_tmp.*T_theta2z_g; 89 | Mo_21 = T_theta2x_tmp.*T_phi2x_g + T_theta2y_tmp.*T_phi2y_g + T_theta2z_tmp.*T_phi2z_g; 90 | Mo_22 = T_phi2x_tmp.*T_phi2x_g + T_phi2y_tmp.*T_phi2y_g + T_phi2z_tmp.*T_phi2z_g; 91 | 92 | %% Reading the original pattern at the rotated signal direction 93 | [ V_org, H_org ] = LinearInterpolate( AntData , phi_mat_new , theta_mat_new ); 94 | 95 | %% Transformation of the polarization 96 | V_new = Mo_11.*V_org + Mo_12.*H_org; 97 | H_new = Mo_21.*V_org + Mo_22.*H_org; 98 | 99 | %% Output 100 | AntData.V = V_new; 101 | AntData.H = H_new; 102 | AntData.T = sqrt(V_new.^2 + H_new.^2); 103 | end 104 | 105 | --------------------------------------------------------------------------------