diff --git a/openair1/SIMULATION/TOOLS/multipath_channel.c b/openair1/SIMULATION/TOOLS/multipath_channel.c index 3045d8ca6c..cff6f85d46 100644 --- a/openair1/SIMULATION/TOOLS/multipath_channel.c +++ b/openair1/SIMULATION/TOOLS/multipath_channel.c @@ -31,7 +31,6 @@ uint8_t multipath_channel_nosigconv(channel_desc_t *desc) { - random_channel(desc,0); return(1); } @@ -163,7 +162,8 @@ void multipath_channel(channel_desc_t *desc, dd = abs(desc->channel_offset); #ifdef DEBUG_CH - printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %d, len %d \n",keep_channel,path_loss,desc->path_loss_dB,desc->nb_rx,desc->nb_tx,dd,desc->channel_length); + printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %d, len %d \n", + keep_channel, path_loss, desc->path_loss_dB, desc->nb_rx, desc->nb_tx, dd, desc->channel_length); #endif if (keep_channel) { @@ -173,12 +173,9 @@ void multipath_channel(channel_desc_t *desc, } #ifdef DEBUG_CH - for (l = 0; l<(int)desc->channel_length; l++) { - printf("%p (%f,%f) ",desc->ch[0],desc->ch[0][l].x,desc->ch[0][l].y); + printf("ch[%i] = (%f, %f)\n", l, desc->ch[0][l].r, desc->ch[0][l].i); } - - printf("\n"); #endif for (i=0; i<((int)length-dd); i++) { @@ -200,7 +197,8 @@ void multipath_channel(channel_desc_t *desc, rx_tmp.i += (tx.i * desc->ch[ii+(j*desc->nb_rx)][l].r) + (tx.r * desc->ch[ii+(j*desc->nb_rx)][l].i); if (i==0 && log_channel == 1) { - printf("channel[%d][%d][%d] = %f dB (%e,%e)\n",ii,j,l,10*log10(pow(desc->ch[ii+(j*desc->nb_rx)][l].r,2.0)+pow(desc->ch[ii+(j*desc->nb_rx)][l].i,2.0)), + printf("channel[%d][%d][%d] = %f dB \t(%e, %e)\n", + ii, j, l, 10*log10(pow(desc->ch[ii+(j*desc->nb_rx)][l].r,2.0)+pow(desc->ch[ii+(j*desc->nb_rx)][l].i,2.0)), desc->ch[ii+(j*desc->nb_rx)][l].r, desc->ch[ii+(j*desc->nb_rx)][l].i); } @@ -209,9 +207,10 @@ void multipath_channel(channel_desc_t *desc, rx_sig_re[ii][i+dd] = rx_tmp.r*path_loss; rx_sig_im[ii][i+dd] = rx_tmp.i*path_loss; -#ifdef DEBUG_CHANNEL +#ifdef DEBUG_CH if ((i%32)==0) { - printf("rx aa %d: %p %p %f,%f => %e,%e\n",ii,rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]); + printf("rx aa %d: %f, %f => %e, %e\n", + ii, rx_tmp.r, rx_tmp.i, rx_sig_re[ii][i-dd], rx_sig_im[ii][i-dd]); } #endif //rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]); diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index 43ed9bab7e..9eb8ebe7e6 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -375,6 +375,7 @@ void tdlModel(int tdl_paths, double *tdl_delays, double *tdl_amps_dB, double DS chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); + chan_desc->ricean_factor = 1.0; for (int i = 0; ich[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); @@ -385,27 +386,69 @@ void tdlModel(int tdl_paths, double *tdl_delays, double *tdl_amps_dB, double DS for (int i = 0; inb_taps; i++) chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); - chan_desc->R_sqrt = (struct complexd **) malloc(tdl_pathsby3*sizeof(struct complexd **)); + // FIXME: Remove this hardcoded value + chan_desc->corr_level = CORR_LEVEL_LOW; - if (nb_tx==2 && nb_rx==2) { - for (int i = 0; i<(tdl_pathsby3); i++) - chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; - } else if (nb_tx==2 && nb_rx==1) { - for (int i = 0; i<(tdl_pathsby3); i++) - chan_desc->R_sqrt[i] = (struct complexd *) &R21_sqrt[i][0]; - } else if (nb_tx==1 && nb_rx==2) { - for (int i = 0; i<(tdl_pathsby3); i++) - chan_desc->R_sqrt[i] = (struct complexd *) &R12_sqrt[i][0]; - } else { - for (int i = 0; i<(tdl_pathsby3); i++) { - chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); - - for (int j = 0; jR_sqrt[i][j].r = 1.0; - chan_desc->R_sqrt[i][j].i = 0.0; + int matrix_size = nb_tx*nb_rx; + double *correlation_matrix[matrix_size]; + if (chan_desc->corr_level!=CORR_LEVEL_LOW) { + if (nb_rx==1 && nb_tx==2) { + for (int row = 0; row < matrix_size; row++) { + correlation_matrix[row] = R12_medium_high[row]; } + } else if (nb_rx==1 && nb_tx==4) { + for (int row = 0; row < matrix_size; row++) { + correlation_matrix[row] = R14_medium_high[row]; + } + } else if (nb_rx==1 && nb_tx==8) { + for (int row = 0; row < matrix_size; row++) { + correlation_matrix[row] = R18_medium_high[row]; + } + } else if (nb_rx==2 && nb_tx==2 && chan_desc->corr_level==CORR_LEVEL_MEDIUM) { + for (int row = 0; row < matrix_size; row++) { + correlation_matrix[row] = R22_medium[row]; + } + } else if (nb_rx==2 && nb_tx==4 && chan_desc->corr_level==CORR_LEVEL_MEDIUM) { + for (int row = 0; row < matrix_size; row++) { + correlation_matrix[row] = R24_medium[row]; + } + } else if (nb_rx==4 && nb_tx==4 && chan_desc->corr_level==CORR_LEVEL_MEDIUM) { + for (int row = 0; row < matrix_size; row++) { + correlation_matrix[row] = R44_medium[row]; + } + } else if (nb_rx==2 && nb_tx==2 && chan_desc->corr_level==CORR_LEVEL_HIGH) { + for (int row = 0; row < matrix_size; row++) { + correlation_matrix[row] = R22_high[row]; + } + } else if (nb_rx==2 && nb_tx==4 && chan_desc->corr_level==CORR_LEVEL_HIGH) { + for (int row = 0; row < matrix_size; row++) { + correlation_matrix[row] = R24_high[row]; + } + } else if (nb_rx==4 && nb_tx==4 && chan_desc->corr_level==CORR_LEVEL_HIGH) { + for (int row = 0; row < matrix_size; row++) { + correlation_matrix[row] = R44_high[row]; + } + } else { + for (int row = 0; row < matrix_size; row++) { + correlation_matrix[row] = NULL; + } + } + } else { + for (int row = 0; row < matrix_size; row++) { + correlation_matrix[row] = NULL; + } + } - LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); + chan_desc->R_sqrt = (struct complexd **) malloc(matrix_size*sizeof(struct complexd **)); + for (int row = 0; row < matrix_size; row++) { + chan_desc->R_sqrt[row] = (struct complexd *) calloc(1, matrix_size*sizeof(struct complexd)); + if (correlation_matrix[row] == NULL) { + // TS 38.104 - Table G.2.3.1.2-4: MIMO correlation matrices for low correlation + chan_desc->R_sqrt[row][row].r = 1.0; + } else { + for (int col = 0; col < matrix_size; col++) { + chan_desc->R_sqrt[row][col].r = correlation_matrix[row][col]; + } } } } @@ -1574,6 +1617,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { struct complexd phase, alpha, beta; start_meas(&desc->random_channel); + bzero(acorr,desc->nb_tx*desc->nb_rx*sizeof(struct complexd)); + for (i=0; i<(int)desc->nb_taps; i++) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { @@ -1612,8 +1657,21 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { */ //apply correlation matrix //compute acorr = R_sqrt[i] * anew - bzero(acorr,desc->nb_tx*desc->nb_rx*sizeof(struct complexd)); - cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) desc->R_sqrt[i/3], (void *) anew, 1, (void *) acorr, 1); + if (desc->modelid >= TDL_A && desc->modelid <= TDL_E) { + for (aatx = 0; aatx < desc->nb_tx; aatx++) { + for (aarx=0; aarxnb_rx; aarx++) { + cblas_zaxpy(desc->nb_tx*desc->nb_rx, + (void *) &anew[aarx+(aatx*desc->nb_rx)], + (void *) desc->R_sqrt[aarx+(aatx*desc->nb_rx)], + 1, + (void *) acorr, + 1); + } + } + } else { + bzero(acorr,desc->nb_tx*desc->nb_rx*sizeof(struct complexd)); + cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) desc->R_sqrt[i/3], (void *) anew, 1, (void *) acorr, 1); + } /* FIXME: Function cblas_zgemv has an undefined output (for the same input) after a second call in RHEL8 (acorr = nan) diff --git a/openair1/SIMULATION/TOOLS/scm_corrmat.h b/openair1/SIMULATION/TOOLS/scm_corrmat.h index 5695e0bd0f..b3e4f0b6ad 100644 --- a/openair1/SIMULATION/TOOLS/scm_corrmat.h +++ b/openair1/SIMULATION/TOOLS/scm_corrmat.h @@ -43,3 +43,97 @@ static double R12_sqrt[6][8] = { {0.991912, 0.000000,0.041738, -0.119870,0.041738, 0.119870,0.991912, 0.000000}, {0.968169, 0.000000,0.216594, -0.125443,0.216594, 0.125443,0.968169, 0.000000}, }; + +// TS 38.104 - Table G.2.3.1.2-2: MIMO correlation matrices for high correlation +static double R22_high[4][4] = { + {1.0, 0.9, 0.9, 0.81}, + {0.9, 1.0, 0.81, 0.9}, + {0.9, 0.81, 1.0, 0.9}, + {0.81, 0.9, 0.9, 1} +}; +static double R24_high[8][8] = { + {1.0000, 0.9883, 0.9542, 0.8999, 0.8999, 0.8894, 0.8587, 0.8099}, + {0.9883, 1.0000, 0.9883, 0.9542, 0.8894, 0.8999, 0.8894, 0.8587}, + {0.9542, 0.9883, 1.0000, 0.9883, 0.8587, 0.8894, 0.8999, 0.8894}, + {0.8999, 0.9542, 0.9883, 1.0000, 0.8099, 0.8587, 0.8894, 0.8999}, + {0.8999, 0.8894, 0.8587, 0.8099, 1.0000, 0.9883, 0.9542, 0.8999}, + {0.8894, 0.8999, 0.8894, 0.8587, 0.9883, 1.0000, 0.9883, 0.9542}, + {0.8587, 0.8894, 0.8999, 0.8894, 0.9542, 0.9883, 1.0000, 0.9883}, + {0.8099, 0.8587, 0.8894, 0.8999, 0.8999, 0.9542, 0.9883, 1.0000} +}; +static double R44_high[16][16] = { + {1.0000, 0.9882, 0.9541, 0.8999, 0.9882, 0.9767, 0.9430, 0.8894, 0.9541, 0.9430, 0.9105, 0.8587, 0.8999, 0.8894, 0.8587, 0.8099}, + {0.9882, 1.0000, 0.9882, 0.9541, 0.9767, 0.9882, 0.9767, 0.9430, 0.9430, 0.9541, 0.9430, 0.9105, 0.8894, 0.8999, 0.8894, 0.8587}, + {0.9541, 0.9882, 1.0000, 0.9882, 0.9430, 0.9767, 0.9882, 0.9767, 0.9105, 0.9430, 0.9541, 0.9430, 0.8587, 0.8894, 0.8999, 0.8894}, + {0.8999, 0.9541, 0.9882, 1.0000, 0.8894, 0.9430, 0.9767, 0.9882, 0.8587, 0.9105, 0.9430, 0.9541, 0.8099, 0.8587, 0.8894, 0.8999}, + {0.9882, 0.9767, 0.9430, 0.8894, 1.0000, 0.9882, 0.9541, 0.8999, 0.9882, 0.9767, 0.9430, 0.8894, 0.9541, 0.9430, 0.9105, 0.8587}, + {0.9767, 0.9882, 0.9767, 0.9430, 0.9882, 1.0000, 0.9882, 0.9541, 0.9767, 0.9882, 0.9767, 0.9430, 0.9430, 0.9541, 0.9430, 0.9105}, + {0.9430, 0.9767, 0.9882, 0.9767, 0.9541, 0.9882, 1.0000, 0.9882, 0.9430, 0.9767, 0.9882, 0.9767, 0.9105, 0.9430, 0.9541, 0.9430}, + {0.8894, 0.9430, 0.9767, 0.9882, 0.8999, 0.9541, 0.9882, 1.0000, 0.8894, 0.9430, 0.9767, 0.9882, 0.8587, 0.9105, 0.9430, 0.9541}, + {0.9541, 0.9430, 0.9105, 0.8587, 0.9882, 0.9767, 0.9430, 0.8894, 1.0000, 0.9882, 0.9541, 0.8999, 0.9882, 0.9767, 0.9430, 0.8894}, + {0.9430, 0.9541, 0.9430, 0.9105, 0.9767, 0.9882, 0.9767, 0.9430, 0.9882, 1.0000, 0.9882, 0.9541, 0.9767, 0.9882, 0.9767, 0.9430}, + {0.9105, 0.9430, 0.9541, 0.9430, 0.9430, 0.9767, 0.9882, 0.9767, 0.9541, 0.9882, 1.0000, 0.9882, 0.9430, 0.9767, 0.9882, 0.9767}, + {0.8587, 0.9105, 0.9430, 0.9541, 0.8894, 0.9430, 0.9767, 0.9882, 0.8999, 0.9541, 0.9882, 1.0000, 0.8894, 0.9430, 0.9767, 0.9882}, + {0.8999, 0.8894, 0.8587, 0.8099, 0.9541, 0.9430, 0.9105, 0.8587, 0.9882, 0.9767, 0.9430, 0.8894, 1.0000, 0.9882, 0.9541, 0.8999}, + {0.8894, 0.8999, 0.8894, 0.8587, 0.9430, 0.9541, 0.9430, 0.9105, 0.9767, 0.9882, 0.9767, 0.9430, 0.9882, 1.0000, 0.9882, 0.9541}, + {0.8587, 0.8894, 0.8999, 0.8894, 0.9105, 0.9430, 0.9541, 0.9430, 0.9430, 0.9767, 0.9882, 0.9767, 0.9541, 0.9882, 1.0000, 0.9882}, + {0.8099, 0.8587, 0.8894, 0.8999, 0.8587, 0.9105, 0.9430, 0.9541, 0.8894, 0.9430, 0.9767, 0.9882, 0.8999, 0.9541, 0.9882, 1.0000} +}; + +// TS 38.104 - Table G.2.3.1.2-3: MIMO correlation matrices for medium correlation +static double R22_medium[4][4] = { + {1.0000, 0.9000, 0.3000, 0.2700}, + {0.9000, 1.0000, 0.2700, 0.3000}, + {0.3000, 0.2700, 1.0000, 0.9000}, + {0.2700, 0.3000, 0.9000, 1.0000} +}; +static double R24_medium[8][8] = { + {1.0000, 0.9884, 0.9543, 0.9000, 0.3000, 0.2965, 0.2863, 0.2700}, + {0.9884, 1.0000, 0.9884, 0.9543, 0.2965, 0.3000, 0.2965, 0.2863}, + {0.9543, 0.9884, 1.0000, 0.9884, 0.2863, 0.2965, 0.3000, 0.2965}, + {0.9000, 0.9543, 0.9884, 1.0000, 0.2700, 0.2863, 0.2965, 0.3000}, + {0.3000, 0.2965, 0.2863, 0.2700, 1.0000, 0.9884, 0.9543, 0.9000}, + {0.2965, 0.3000, 0.2965, 0.2863, 0.9884, 1.0000, 0.9884, 0.9543}, + {0.2863, 0.2965, 0.3000, 0.2965, 0.9543, 0.9884, 1.0000, 0.9884}, + {0.2700, 0.2863, 0.2965, 0.3000, 0.9000, 0.9543, 0.9884, 1.0000} +}; +static double R44_medium[16][16] = { + {1.0000, 0.9882, 0.9541, 0.8999, 0.8747, 0.8645, 0.8347, 0.7872, 0.5855, 0.5787, 0.5588, 0.5270, 0.3000, 0.2965, 0.2862, 0.2700}, + {0.9882, 1.0000, 0.9882, 0.9541, 0.8645, 0.8747, 0.8645, 0.8347, 0.5787, 0.5855, 0.5787, 0.5588, 0.2965, 0.3000, 0.2965, 0.2862}, + {0.9541, 0.9882, 1.0000, 0.9882, 0.8347, 0.8645, 0.8747, 0.8645, 0.5588, 0.5787, 0.5855, 0.5787, 0.2862, 0.2965, 0.3000, 0.2965}, + {0.8999, 0.9541, 0.9882, 1.0000, 0.7872, 0.8347, 0.8645, 0.8747, 0.5270, 0.5588, 0.5787, 0.5855, 0.2700, 0.2862, 0.2965, 0.3000}, + {0.8747, 0.8645, 0.8347, 0.7872, 1.0000, 0.9882, 0.9541, 0.8999, 0.8747, 0.8645, 0.8347, 0.7872, 0.5855, 0.5787, 0.5588, 0.5270}, + {0.8645, 0.8747, 0.8645, 0.8347, 0.9882, 1.0000, 0.9882, 0.9541, 0.8645, 0.8747, 0.8645, 0.8347, 0.5787, 0.5855, 0.5787, 0.5588}, + {0.8347, 0.8645, 0.8747, 0.8645, 0.9541, 0.9882, 1.0000, 0.9882, 0.8347, 0.8645, 0.8747, 0.8645, 0.5588, 0.5787, 0.5855, 0.5787}, + {0.7872, 0.8347, 0.8645, 0.8747, 0.8999, 0.9541, 0.9882, 1.0000, 0.7872, 0.8347, 0.8645, 0.8747, 0.5270, 0.5588, 0.5787, 0.5855}, + {0.5855, 0.5787, 0.5588, 0.5270, 0.8747, 0.8645, 0.8347, 0.7872, 1.0000, 0.9882, 0.9541, 0.8999, 0.8747, 0.8645, 0.8347, 0.7872}, + {0.5787, 0.5855, 0.5787, 0.5588, 0.8645, 0.8747, 0.8645, 0.8347, 0.9882, 1.0000, 0.9882, 0.9541, 0.8645, 0.8747, 0.8645, 0.8347}, + {0.5588, 0.5787, 0.5855, 0.5787, 0.8347, 0.8645, 0.8747, 0.8645, 0.9541, 0.9882, 1.0000, 0.9882, 0.8347, 0.8645, 0.8747, 0.8645}, + {0.5270, 0.5588, 0.5787, 0.5855, 0.7872, 0.8347, 0.8645, 0.8747, 0.8999, 0.9541, 0.9882, 1.0000, 0.7872, 0.8347, 0.8645, 0.8747}, + {0.3000, 0.2965, 0.2862, 0.2700, 0.5855, 0.5787, 0.5588, 0.5270, 0.8747, 0.8645, 0.8347, 0.7872, 1.0000, 0.9882, 0.9541, 0.8999}, + {0.2965, 0.3000, 0.2965, 0.2862, 0.5787, 0.5855, 0.5787, 0.5588, 0.8645, 0.8747, 0.8645, 0.8347, 0.9882, 1.0000, 0.9882, 0.9541}, + {0.2862, 0.2965, 0.3000, 0.2965, 0.5588, 0.5787, 0.5855, 0.5787, 0.8347, 0.8645, 0.8747, 0.8645, 0.9541, 0.9882, 1.0000, 0.9882}, + {0.2700, 0.2862, 0.2965, 0.3000, 0.5270, 0.5588, 0.5787, 0.5855, 0.7872, 0.8347, 0.8645, 0.8747, 0.8999, 0.9541, 0.9882, 1.0000} +}; + +// Matrices computed based on TS 38.104 - Tables G.2.3.1.1-3 and G.2.3.1.2-1 +static double R12_medium_high[2][2] = { + {1.0, 0.9}, + {0.9, 1.0} +}; +static double R14_medium_high[4][4] = { + {1.000000, 0.988362, 0.954253, 0.900000}, + {0.988362, 1.000000, 0.988362, 0.954253}, + {0.954253, 0.988362, 1.000000, 0.988362}, + {0.900000, 0.954253, 0.988362, 1.000000}, +}; +static double R18_medium_high[8][8] = { + {1.000000, 0.997852, 0.991436, 0.980834, 0.966182, 0.947664, 0.925512, 0.900000}, + {0.997852, 1.000000, 0.997852, 0.991436, 0.980834, 0.966182, 0.947664, 0.925512}, + {0.991436, 0.997852, 1.000000, 0.997852, 0.991436, 0.980834, 0.966182, 0.947664}, + {0.980834, 0.991436, 0.997852, 1.000000, 0.997852, 0.991436, 0.980834, 0.966182}, + {0.966182, 0.980834, 0.991436, 0.997852, 1.000000, 0.997852, 0.991436, 0.980834}, + {0.947664, 0.966182, 0.980834, 0.991436, 0.997852, 1.000000, 0.997852, 0.991436}, + {0.925512, 0.947664, 0.966182, 0.980834, 0.991436, 0.997852, 1.000000, 0.997852}, + {0.900000, 0.925512, 0.947664, 0.966182, 0.980834, 0.991436, 0.997852, 1.000000} +}; \ No newline at end of file diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index 64842cfa63..8068cba53b 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -50,6 +50,13 @@ typedef enum { #define CHANMODEL_FREE_RSQRT_6 1<<1 #define CHANMODEL_FREE_RSQRT_NTAPS 1<<2 #define CHANMODEL_FREE_AMPS 1<<3 + +typedef enum { + CORR_LEVEL_LOW, + CORR_LEVEL_MEDIUM, + CORR_LEVEL_HIGH +} corr_level_t; + typedef struct { ///Number of tx antennas uint8_t nb_tx; @@ -75,8 +82,10 @@ typedef struct { double channel_bandwidth; ///System sampling rate in Msps. double sampling_rate; - ///Ricean factor of first tap wrt other taps (0..1, where 0 means AWGN and 1 means Rayleigh channel). + ///Ricean factor, sqrt(1/(K+1)), of first tap wrt other taps (0..1, where 0 means AWGN and 1 means Rayleigh channel). double ricean_factor; + ///Correlation level of correlation channel matrix + corr_level_t corr_level; ///Angle of arrival of wavefront (in radians). For Ricean channel only. This assumes that both RX and TX have linear antenna arrays with lambda/2 antenna spacing. Furhter it is assumed that the arrays are parallel to each other and that they are far enough apart so that we can safely assume plane wave propagation. double aoa; ///If set to 1, aoa is randomized according to a uniform random distribution