├── README.md ├── main.m ├── LICENSE ├── GetConfig.m ├── SupPoint.m └── CRBcal.m /README.md: -------------------------------------------------------------------------------- 1 | # Beyond-5G-RIS-mmWave-Systems-Where-Communication-and-Localization-Meet 2 | PEB and NLOS spectral density (SE) for a SISO system equipped with a single RIS. The BS and RIS are located at $(1,1,0)$ and $(0,0,0)$, respectively, and the user is placed on the $(x,y,-y)$ plane. The rest of the parameters can be found in https://arxiv.org/abs/2011.02391. 3 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | 2 | close all;clear all;clc; 3 | %% generating ris profile 4 | config = GetConfig(); 5 | rng(100) 6 | crb = CRBcal(config); 7 | crb = crb.PEBcalc; % calculating PEB 8 | Rate = crb.getRate; 9 | 10 | %% plots 11 | 12 | % --------------- random, PEB 13 | figure 14 | [X,Y] = meshgrid(crb.config.xvec,crb.config.yvec); 15 | crbR = reshape(crb.PEB,size(X)); 16 | contourf(X,Y,crbR,10.^[-4:.5:0],'--') 17 | set(gca,'ColorScale','log') 18 | xlabel('x (m)');ylabel('y(m)'); 19 | title('PEB (m)'); 20 | cl = colorbar; 21 | 22 | 23 | %---------------------------- random SE--------- 24 | figure 25 | crbR = reshape(Rate.rate_rand,size(X)); 26 | contourf(X,Y,crbR,[.03,.1,.2,.5,1],'--') 27 | xlabel('x (m)');ylabel('y(m)'); 28 | title('SE (bits/sec/Hz)'); 29 | cl = colorbar; 30 | 31 | 32 | %------------------------------------------directional SE-------- 33 | figure 34 | crbR = reshape(min(Rate.rate_dir,15),size(X)); 35 | contourf(X,Y,crbR,[0:.2:1,1:10],'--') 36 | hold on 37 | xlabel('x (m)');ylabel('y(m)'); 38 | title('Rate (bits/sec/Hz)'); 39 | cl = colorbar; 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 KamranKeykhosravi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /GetConfig.m: -------------------------------------------------------------------------------- 1 | function config = GetConfig() 2 | %returns a structure of the configuration 3 | config.secFactor = 1e9; % time scaling factor 1e9 means that time is in 4 | %nano seconds and frequency in GHz 5 | config.c = 3e8/config.secFactor; %light speed m/ns 6 | %% ofdm 7 | config.f = 30e9/config.secFactor; %frequency Ghz 8 | config.Df= 120e3/config.secFactor;%bandwidth Ghz 9 | config.Nsc = 3e3;% Subcarrier number 10 | config.T = 256;% Subcarrier number 11 | config.lambda = config.c/config.f; 12 | %% geometry 13 | config.bsPos = [1,1,0]; % Bs position 14 | config.risPos = [0,0,0]; % RIS position 15 | config.Mc = 64; % number of RIS elements in a row 16 | config.risElementDist = .5*config.lambda; % RIS element distance 17 | config.TxPower = 100e-3; % transmit power 18 | config.NPSD = 1e-3*10^(-174/10)*config.secFactor; % noise spectral density 19 | config.Noise_Factor = 10^(8/10); % noise factor 20 | % ------------------------ 21 | config.sigmaPriorInf =1; %the initial position uncertenty 22 | config.PointsNum=30; % number of points that is considered in FIG 1 23 | config.xvec = [-10:-1,-.5,.5,1:10]; 24 | config.yvec = [0.5,1:10]; 25 | [X,Y] = meshgrid(config.xvec,config.yvec); 26 | config.xyz = [X(:).';Y(:).';-Y(:).'];%contians xyz corrdinates of the points 27 | end 28 | 29 | -------------------------------------------------------------------------------- /SupPoint.m: -------------------------------------------------------------------------------- 1 | classdef SupPoint 2 | % This object represents a super point which have X, Y, and Z 3 | % dimensions, where the three dimensions are matrices of same size 4 | %(Z can be a scalar which indicates all the points have the same Z) 5 | % this class is made to deal with multipe locations points at once which makes 6 | 7 | properties 8 | X %matrix of X positions 9 | Y %matrix of Y positions 10 | Z %z positions 11 | sinAz %sin of Azimuth 12 | cosAz %cos of Azimuth 13 | sinEl %sin of Elevation 14 | cosEl %cos of Elevation 15 | XY2 %X.^2+Y.^2 16 | XY %sqrt(X.^2+Y.^2) 17 | abs2 %X.^2+Y.^2+z.^2 18 | abs %sqrt(X.^2+Y.^2+z.^2) 19 | end 20 | methods 21 | function obj=SupPoint(X,Y,Z) 22 | % Constructor gets either three matrices or one 1X3 vector 23 | 24 | if nargin ==1 % in case a 1X3 vector is passed 25 | Y = X(2); 26 | Z = X(3); 27 | X = X(1); 28 | end 29 | obj.X = X; 30 | obj.Y = Y; 31 | obj.Z = Z; 32 | obj = obj.calcProperties; 33 | end 34 | function obj = calcProperties(obj) 35 | % calculates the attributes of superpoint 36 | 37 | obj.XY2 = obj.X.^2+obj.Y.^2; 38 | obj.XY = sqrt(obj.XY2); 39 | obj.abs2 = obj.XY2+obj.Z.^2; 40 | obj.abs = sqrt(obj.abs2); 41 | obj.cosAz = obj.X./obj.XY; 42 | obj.sinAz = obj.Y./obj.XY; 43 | obj.cosEl = obj.Z./obj.abs; 44 | obj.sinEl = obj.XY./obj.abs; 45 | end 46 | 47 | %% 48 | 49 | function k = getKv(obj,lambda) 50 | % calculates the wavenumber vector 51 | k = -1*[(2*pi/lambda)*obj.sinEl(:).*obj.cosAz(:),(2*pi/lambda)*obj.sinEl(:).*obj.sinAz(:),(2*pi/lambda)*obj.cosEl(:)]; 52 | end 53 | function k = getKDazv(obj,lambda) 54 | % calculates the derivative of the wavenumber vector with 55 | % respect to Azimuth angle 56 | k = -1*[-(2*pi/lambda)*obj.sinEl(:).*obj.sinAz(:),(2*pi/lambda)*obj.sinEl(:).*obj.cosAz(:),zeros(length(obj.cosAz(:)),1)]; 57 | end 58 | function k = getKDelv(obj,lambda) 59 | % calculates the derivative of the wavenumber vector with 60 | % respect to Elevation angle 61 | k = -1*[(2*pi/lambda)*obj.cosEl(:).*obj.cosAz(:),(2*pi/lambda)*obj.cosEl(:).*obj.sinAz(:),-(2*pi/lambda)*obj.sinEl(:)]; 62 | end 63 | 64 | %% 65 | function v = getV(obj,i,j) 66 | % outputs the 1X3 vector of dimensions of the point i,j 67 | 68 | if length(obj.Z) == 1 69 | z=obj.Z; 70 | else 71 | z=obj.Z(i,j); 72 | end 73 | v=[obj.X(i,j), obj.Y(i,j), z]; 74 | end 75 | end 76 | end -------------------------------------------------------------------------------- /CRBcal.m: -------------------------------------------------------------------------------- 1 | classdef CRBcal 2 | properties 3 | config % contains the config 4 | risElementLoc %contias the location of ris elements 5 | IV %stores some initial calculations for channel parameters 6 | FIMch % fisher information matrix for channel parameters 7 | FIMpo %fisher information matrix for positional parametrs 8 | PEB %peb vector 9 | Jacob %jacobian matrix 10 | end 11 | 12 | methods 13 | function obj = CRBcal(config) 14 | % constructor: input the config file and the Ris phase profile 15 | obj.config = config; 16 | obj.risElementLoc = obj.getRisElLoc; 17 | obj = obj.getInits; 18 | end 19 | 20 | function RisElLoc = getRisElLoc(obj) 21 | % calculates a 3XM matrix containing ris element locations 22 | Lris = (obj.config.Mc-1)*obj.config.risElementDist; 23 | risXvec = linspace(0,Lris,obj.config.Mc)-Lris/2; 24 | risZvec = risXvec; 25 | [risX, risZ] = meshgrid(risXvec,risZvec); 26 | RisElLoc= [risX(:),zeros(length(risX(:)),1),risZ(:)]; 27 | end 28 | 29 | function obj = getInits(obj) 30 | % calculates some initial values like channel parameters and 31 | % Power, noise variance , and poistions 32 | 33 | obj.IV.sqEs = sqrt(obj.config.TxPower/obj.config.Nsc); %quare root symbol energy 34 | obj.IV.sqN = sqrt(obj.config.Noise_Factor*obj.config.NPSD*obj.config.Df/2);%square root noise power 35 | obj.IV.snr = obj.config.TxPower/(obj.config.Nsc*obj.config.Noise_Factor*obj.config.NPSD*obj.config.Df); 36 | 37 | obj.IV.uePos = SupPoint(obj.config.xyz(1,:),obj.config.xyz(2,:),obj.config.xyz(3,:)); %ue positions 38 | obj.IV.BsPos = SupPoint(obj.config.bsPos); %Bs positon 39 | obj.IV.BsUeVec = SupPoint(obj.IV.uePos.X-obj.IV.BsPos.X, obj.IV.uePos.Y-obj.IV.BsPos.Y, obj.IV.uePos.Z-obj.IV.BsPos.Z);% vector from Bs to Ue 40 | 41 | obj.IV.gb = sqrt((obj.config.lambda./(4*pi*obj.IV.BsUeVec.abs(:))).^2).*exp(2*pi*1j*rand(size(obj.IV.BsUeVec.abs(:)))); % los gain 42 | obj.IV.gr = sqrt((obj.config.lambda./(4*pi*obj.IV.BsPos.abs(:))).^2 .* (obj.config.lambda./(4*pi*obj.IV.uePos.abs(:))).^2).*exp(2*pi*1j*rand(size(obj.IV.BsUeVec.abs(:)))); % reflected path gatin 43 | obj.IV.tau_b = obj.IV.BsUeVec.abs(:)./obj.config.c; % los ToA 44 | obj.IV.tau_r = (obj.IV.BsPos.abs(:)+obj.IV.uePos.abs(:))./obj.config.c; % NLOS TOA 45 | obj.IV.k = obj.IV.uePos.getKv(obj.config.lambda); % wavenumber vector 46 | obj.IV.kaz = obj.IV.uePos.getKDazv(obj.config.lambda); %d k /d \phi_az 47 | obj.IV.kel = obj.IV.uePos.getKDelv(obj.config.lambda); 48 | obj.IV.RisPhaseProfile = exp(1j*2*pi*rand(obj.config.Mc^2,obj.config.T)); 49 | obj.IV.ur = exp(-1j*obj.IV.k*obj.risElementLoc.') * obj.IV.RisPhaseProfile; % u_r 50 | obj.IV.urAz = (exp(-1j*obj.IV.k*obj.risElementLoc.').* (-1j*obj.IV.kaz*obj.risElementLoc.')) * obj.IV.RisPhaseProfile; 51 | obj.IV.urEl = (exp(-1j*obj.IV.k*obj.risElementLoc.').* (-1j*obj.IV.kel*obj.risElementLoc.')) * obj.IV.RisPhaseProfile; 52 | 53 | end 54 | 55 | function Rate = getRate(obj) 56 | % calculates the Spectral Efficiency for random and directional 57 | % ris phase profiles 58 | rng(0) 59 | NoisePW= (obj.config.Nsc*obj.config.Noise_Factor*obj.config.NPSD*obj.config.Df); 60 | Rate.rate_rand = zeros(size(obj.IV.k,1),1); 61 | Nn=1000; 62 | for i=1:Nn 63 | RisPhaseProfile = exp(1j*2*pi*rand(obj.config.Mc^2,1)); 64 | ur = exp(-1j*obj.IV.k*obj.risElementLoc.') * RisPhaseProfile; 65 | cyclicPrifix=1.07; 66 | 67 | snr_rand = (obj.config.TxPower*abs(obj.IV.gr.* ur).^2)./NoisePW; 68 | Rate.rate_rand = Rate.rate_rand+log2(1+snr_rand)/cyclicPrifix; 69 | end 70 | Rate.rate_rand = Rate.rate_rand/Nn; 71 | 72 | Rate.rate_dir = zeros(size(Rate.rate_rand)); 73 | Nn=100; 74 | for p = 1:size(ur,1) 75 | P=obj.IV.uePos.getV(1,p); 76 | peb = obj.PEB(p); 77 | sig = peb/sqrt(3); 78 | for n=1:Nn 79 | Pn = P + randn(1,3)*sig/sqrt(3); 80 | uePos = SupPoint(Pn(1),Pn(2),Pn(3)); 81 | k = uePos.getKv(obj.config.lambda); 82 | RisPhaseProfile = exp(1j*k*obj.risElementLoc.').'; 83 | ur = exp(-1j*obj.IV.k(p,:)*obj.risElementLoc.') * RisPhaseProfile; 84 | snr_dir = (obj.config.TxPower*abs(obj.IV.gr(p).*ur).^2)./NoisePW; 85 | Rate.rate_dir(p) = Rate.rate_dir(p)+log2(1+snr_dir)/cyclicPrifix; 86 | end 87 | Rate.rate_dir(p)=Rate.rate_dir(p)/Nn; 88 | end 89 | 90 | 91 | end 92 | 93 | 94 | 95 | function Jc = getJacobian(obj) 96 | % returens a cell of the length of number of points each with a 8X8 jacobian matrix 97 | J = cell(8,8); 98 | J{1,1} = 1/obj.config.c*(obj.IV.uePos.X-obj.IV.BsPos.X)./(obj.IV.BsUeVec.abs); %d\tau_{b}/d\p1 99 | J{1,2} = 1/obj.config.c*(obj.IV.uePos.Y-obj.IV.BsPos.Y)./(obj.IV.BsUeVec.abs); %d\tau_{b}/d\p2 100 | J{1,3} = 1/obj.config.c*(obj.IV.uePos.Z-obj.IV.BsPos.Z)./(obj.IV.BsUeVec.abs); %d\tau_{b}/d\p3 101 | J{2,1} = 1/obj.config.c*(obj.IV.uePos.X)./(obj.IV.uePos.abs); %d\tau_{r}/d\p1 102 | J{2,2} = 1/obj.config.c*(obj.IV.uePos.Y)./(obj.IV.uePos.abs); %d\tau_{r}/d\p2 103 | J{2,3} = 1/obj.config.c*(obj.IV.uePos.Z)./(obj.IV.uePos.abs); %d\tau_{r}/d\p3 104 | J{3,1} = -obj.IV.uePos.Y./(obj.IV.uePos.XY2); %d\phi_{az}/d\p1 105 | J{3,2} = obj.IV.uePos.X./(obj.IV.uePos.XY2); %d\phi_{az}/d\p1 106 | J{4,1} = obj.IV.uePos.X.*obj.IV.uePos.Z./(obj.IV.uePos.abs2.*obj.IV.uePos.XY); %d\phi_{el}/d\p1 107 | J{4,2} = obj.IV.uePos.Y.*obj.IV.uePos.Z./(obj.IV.uePos.abs2.*obj.IV.uePos.XY); %d\phi_{el}/d\p2 108 | J{4,3} = (-obj.IV.uePos.abs2 + obj.IV.uePos.Z.*obj.IV.uePos.Z)./(obj.IV.uePos.abs2.*obj.IV.uePos.XY); %d\phi_{el}/d\p3 109 | Jc = cell(size(obj.IV.uePos.X)); 110 | for ir=1:size(obj.IV.uePos.X,1) 111 | for ic=1:size(obj.IV.uePos.X,2) 112 | Jc{ir,ic}=[J{1,1}(ir,ic),J{1,2}(ir,ic),J{1,3}(ir,ic),1,0,0,0,0;... 113 | J{2,1}(ir,ic),J{2,2}(ir,ic),J{2,3}(ir,ic),1,0,0,0,0;... 114 | J{3,1}(ir,ic),J{3,2}(ir,ic),0,0,0,0,0,0;... 115 | J{4,1}(ir,ic),J{4,2}(ir,ic),J{4,3}(ir,ic),0,0,0,0,0;... 116 | 0,0,0,0,1,0,0,0;0,0,0,0,0,1,0,0;0,0,0,0,0,0,1,0;0,0,0,0,0,0,0,1]; 117 | end 118 | end 119 | end 120 | 121 | function FIMch = getFIMCh(obj) 122 | % calculates the fisher information matrix for channel 123 | % parameters 124 | db = exp(-1j*2*pi*mod(obj.config.Df*obj.IV.tau_b*[0:obj.config.Nsc-1],1)); 125 | dr = exp(-1j*2*pi*mod(obj.config.Df*obj.IV.tau_r*[0:obj.config.Nsc-1],1)); 126 | d = -1j*2*pi*[0:obj.config.Nsc-1]*obj.config.Df; 127 | FIMch = cell(1,size(obj.config.xyz,2)); 128 | tic 129 | for ip = 1:size(obj.config.xyz,2) 130 | fprintf('Calculating CRB %.2f %% done! \n', (ip-1)/size(obj.config.xyz,2)*100); 131 | FIMch{1,ip} = zeros(8); 132 | for it = 1:obj.config.T 133 | for in = 1:obj.config.Nsc 134 | u = [ 135 | d(in)*obj.IV.gb(ip)*db(ip,in),... 136 | d(in)*obj.IV.gr(ip)*dr(ip,in)*obj.IV.ur(ip,it),... 137 | obj.IV.gr(ip)*dr(ip,in)*obj.IV.urAz(ip,it),... 138 | obj.IV.gr(ip)*dr(ip,in)*obj.IV.urEl(ip,it),... 139 | db(ip,in),... 140 | 1j*db(ip,in),... 141 | dr(ip,in)*obj.IV.ur(ip,it),... 142 | 1j*dr(ip,in)*obj.IV.ur(ip,it),... 143 | ]; 144 | FIMch{1,ip} = FIMch{1,ip} + 2*obj.IV.snr* real(u'*u); 145 | end 146 | end 147 | ElTime = toc; 148 | fprintf('Est. remaining time: %.2f minuites \n', ElTime/ip*(size(obj.config.xyz,2)-ip)/60); 149 | 150 | end 151 | end 152 | 153 | function obj = PEBcalc(obj) 154 | %calculates fisher information for positional parameters and 155 | %PEB 156 | obj.Jacob = obj.getJacobian; 157 | obj.FIMch = obj.getFIMCh; 158 | obj.FIMpo = cell(1,size(obj.config.xyz,2)); 159 | obj.PEB = zeros(1,size(obj.config.xyz,2)); 160 | for ip = 1:size(obj.config.xyz,2) 161 | Jcb = obj.Jacob{1,ip}; 162 | obj.FIMpo{1,ip} = Jcb.' * obj.FIMch{1,ip} * Jcb; 163 | 164 | fim = obj.FIMpo{1,ip};% using Schur’s complement 165 | A = fim(1:4,1:4); 166 | B = fim(1:4,5:8); 167 | C = fim(5:8,1:4); 168 | D = fim(5:8,5:8); 169 | eqFim = A-B*inv(D)*C; 170 | FimInv = inv(eqFim); 171 | obj.PEB(1,ip) = sqrt(trace(FimInv(1:3,1:3))); 172 | end 173 | end 174 | 175 | 176 | 177 | end 178 | end 179 | 180 | 181 | --------------------------------------------------------------------------------