├── 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 | 
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 | 
53 |
54 | The following results are reproduced from Fig. 12(b) of our paper:
55 | 
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 |
--------------------------------------------------------------------------------