Comparing the CDL Channel results with Matlab
Compare the results of this notebook with the Matlab file CDLTest.mlx
in the MatlabFiles
directory.
The “.mat” files in the MatlabFiles
directory were created by Matlab running the CDLTest.mlx
file. If you want to recreate these files, follow the instructions in the Matlab file. Here is the execution results of this code in Matlab.
[1]:
import numpy as np
import scipy.io
from neoradium import Carrier, CdlChannel, AntennaPanel, random
from neoradium.utils import getNmse
matlabFilesPath = "./MatlabFiles"
CDL Channel Model
Now we want to create a CDL Channel object (CdlChannel
) and apply it to the time-domain waveform.
Note 1: Since CDL is a statistical model, there is always a randomness with the way the phases are initialized and the way rays are coupled. The getMatlabRandomInit
helper function can be used to create the same random initial phases and ray couplings that are generated by the Matlab code.
Note 2: The NeoRadium’s implementation of FIR filters used by the CDL channel is slightly different from Matlab. To compensate for this difference we need to modify the stopBandAttenuation
parameter. See the documentation of ChannelFilter
class for more information.
[4]:
carrier = Carrier(startRb=0, numRbs=25, spacing=15) # Carrier 25 Resource Blocks, 15KHz subcarrier spacing
bwp = carrier.curBwp # The only bandwidth part in the carrier
cdlModel = 'D'
seed = 123
phiInit, coupling = CdlChannel.getMatlabRandomInit(cdlModel, seed) # Match Matlab random values
speedKmh = 15 # speed of UE device: 15 km/h
speed = speedKmh*1000/3600 # m/s
c = 299792458 # Speed of light
fc = 4e9 # 4 GHz
d = speed*fc/c # Doppler Shift (Hz)
# Create the channel model
channel = CdlChannel(bwp, cdlModel, delaySpread=10, carrierFreq=fc, dopplerShift=d,
initialPhases = phiInit, rayCoupling = coupling,
txAntenna = AntennaPanel([2,2], polarization="x", matlabOrder=True),
rxAntenna = AntennaPanel([1,1], polarization="+", matlabOrder=True),
txOrientation = [10, 20, 30],
rxOrientation = [0, 0, 0], # The default is [180, 0, 0]
angleScaling = ([130,70,80,110], [5,11,3,3]), # Angle Scaling
stopBandAtten = 70,
)
channel.print()
CDL-D Channel Properties:
carrierFreq: 4 GHz
normalizeGains: True
normalizeOutput: True
txDir: Downlink
filterLen: 16 samples
delayQuantSize: 64
stopBandAtten: 70 db
dopplerShift: 55.59401586635868 Hz
coherenceTime: 7.611 milliseconds
delaySpread: 10 ns
ueDirAZ: 0.0°, 90.0°
Angle Scaling:
Means: 130° 70° 80° 110°
RMS Spreads: 5° 11° 3° 3°
Cross Pol. Power: 11 db
angleSpreads: 5° 8° 3° 3°
TX Antenna:
Total Elements: 8
spacing: 0.5𝜆, 0.5𝜆
shape: 2 rows x 2 columns
polarization: x
RX Antenna:
Total Elements: 2
spacing: 0.5𝜆, 0.5𝜆
shape: 1 rows x 1 columns
polarization: +
Orientation (𝛼,𝛃,𝛄): 0° 0° 0°
hasLOS: True
LOS Path:
Delay (ns): 0.00000
Power (db): -0.20000
AOD (Deg): 0
AOA (Deg): -3
ZOD (Deg): 1
ZOA (Deg): 1
NLOS Paths (13):
Delays (ns): 0.000 0.350 6.120 13.63 14.05 18.04 25.96 17.75 40.42 79.37 94.24 97.08
125.2
Powers (db): -13.5 -18.8 -21.0 -22.8 -17.9 -20.1 -21.9 -22.9 -27.8 -23.6 -24.8 -30.0
-27.7
AODs (Deg): 0 89 89 89 13 13 13 35 -64 -33 53 -132
77
AOAs (Deg): -180 89 89 89 163 163 163 -137 74 128 -120 -9
-84
ZODs (Deg): 98 86 86 86 98 98 98 98 88 91 104 80
86
ZOAs (Deg): 82 87 87 87 79 79 79 78 74 78 87 71
73
Applying the channel to a random waveform
Now we create a random waveform 1 subframe long (1 ms) and apply our CDL Channel to the waveform. To compare the results with Matlab, we read the waveform from a file created by the Matlab program CDLTest.mlx
.
[5]:
# Create a random signal for 1 subframe (1 ms)
t = 0.001 # 1 subframe = 1 ms
numInputSamples = int(channel.sampleRate * t)
nr, nt = channel.nrNt # Get the number of antanna from the channel
# Load the "txWaveform" generated by the Matlab code
txWaveform = scipy.io.loadmat(matlabFilesPath+'/txWaveform.mat')['txWaveform'].T
assert txWaveform.shape==(nt, numInputSamples)
# Check the following numbers with the Matlabmatlab-generated numbers to make sure we are using
# the same input signal:
print("TX Waveform Data:\n", np.round(txWaveform[2:4,200:204].T,4)) # Matlab: txWaveform(201:204,3:4)
# Use the following line instead of above line to create a random signal (The result will be
# different from Matlab)
# txWaveform = np.random.normal(size=(numSamples, nt)) + 1j*np.random.normal(size=(numSamples, nt))
# Now apply the channel to the waveform
rxWaveform = channel.applyToSignal(txWaveform)
print("RX Waveform Data:\n", np.round(rxWaveform[1,200:204].T,4)) # Matlab: rxWaveform(201:204,2)
# Load Matlab results and compare with the above results
rxWaveformMatlab = scipy.io.loadmat(matlabFilesPath+'/rxWaveform.mat')['rxWaveform']
assert rxWaveformMatlab.shape==(numInputSamples, nr)
print("NMSE:", getNmse(rxWaveformMatlab.T,rxWaveform.waveform)) # NMSE between NeoRadium and Matlab results
TX Waveform Data:
[[-0.6478-0.1199j -0.2126+1.1219j]
[ 0.2027-0.3657j -0.235 +0.5164j]
[ 0.2795+0.0952j -1.5704-1.3598j]
[ 1.0207+0.3367j 0.2162-1.0988j]]
RX Waveform Data:
[-0.009 +0.0549j 0.0091-0.0461j 0.0009+0.0113j 0.0247-0.0103j]
NMSE: 0.00017640878177951165
[ ]: