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 CdlChannel, AntennaPanel, random
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.
[2]:
cdlModel = 'D'
seed = 123
phiInit, coupling = CdlChannel.getMatlabRandomInit(cdlModel, seed)
stopBandAttenuation = 70
# Our calculation of beta is different from Matlab (See the ChannelFilter.getMultiRateFIR method)
# The following code compensates for the difference:
stopBandAttenuation += 8.861-8.71 # We use "8.861"; Matlab uses "8.71". See Note 2 above.
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('D', 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],
angleScaling = ([130,70,80,110], [5,11,3,3]), # Angle Scaling
stopBandAtten = stopBandAttenuation,
timing = 'Matlab') # Use Matlabmatlab timing only when comparing results with Matlab
channel.print()
CDL-D Channel Properties:
delaySpread: 10 ns
dopplerShift: 55.59401586635868 Hz
carrierFreq: 4000000000.0 Hz
normalizeGains: True
normalizeOutput: True
txDir: Downlink
timing method: Matlab
coherenceTime: 0.007611 (Sec.)
ueDirAZ: 0°, 90°
Angle Scaling:
Means: 130° 70° 80° 110°
RMS Spreads: 5° 11° 3° 3°
pathDelays (ns): 0.0000 0.0000 0.3500 6.1200 13.630 14.050 18.040 25.960 17.750 40.420
79.370 94.240 97.080 125.25
pathPowers (db): -0.200 -13.50 -18.80 -21.00 -22.80 -17.90 -20.10 -21.90 -22.90 -27.80
-23.60 -24.80 -30.00 -27.70
AODs (Degree): 0 0 89 89 89 13 13 13 35 -64 -33 53 -132 77
AOAs (Degree): -180 -180 89 89 89 163 163 163 -137 74 128 -120 -9 -84
ZODs (Degree): 98 98 86 86 86 98 98 98 98 88 91 104 80 86
ZOAs (Degree): 82 82 87 87 87 79 79 79 78 74 78 87 71 73
hasLOS: True
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
taper: 1.0
TX Antenna Orientation (𝛼,𝛃,𝛄): 10° 20° 30°
RX Antenna:
Total Elements: 2
spacing: 0.5𝜆, 0.5𝜆
shape: 1 rows x 1 columns
polarization: +
taper: 1.0
Channel Filter:
filterDelay (samples): 7
numTxAntenna: 8
numPaths: 14
pathDelays (ns): 0.0000 0.0000 0.3500 6.1200 13.630 14.050 18.040 25.960 17.750 40.420
79.370 94.240 97.080 125.25
filterLen: 16
numInterpol: 50
normalize: True
stopBandAtten: 70.151
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
.
[3]:
# 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 Matlab-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)
diffAbs = np.abs(rxWaveformMatlab.T-rxWaveform.waveform)
print("Maximum Difference:", diffAbs.max()) # Maximum difference 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.0091+0.0549j 0.0093-0.0458j 0.0008+0.0113j 0.025 -0.0101j]
Maximum Difference: 1.5649542371081303e-10
[ ]: