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
[ ]: