25 #include "ns3/phased-array-model.h"
27 #include "ns3/double.h"
28 #include "ns3/string.h"
29 #include "ns3/integer.h"
33 #include <ns3/simulator.h>
34 #include "ns3/mobility-model.h"
35 #include "ns3/pointer.h"
45 0.0447, -0.0447, 0.1413, -0.1413, 0.2492, -0.2492, 0.3715, -0.3715, 0.5129, -0.5129,
46 0.6797, -0.6797, 0.8844, -0.8844, 1.1481, -1.1481, 1.5195, -1.5195, 2.1551, -2.1551};
57 {1, 0, 0, 0, 0, 0, 0},
58 {0, 1, 0, 0, 0, 0, 0},
59 {-0.5, 0, 0.866025, 0, 0, 0, 0},
60 {0, 0, 0, 1, 0, 0, 0},
61 {0, 0, 0, 0, 1, 0, 0},
62 {0.01, 0, -0.0519615, 0.73, -0.2, 0.651383, 0},
63 {-0.17, -0.02, 0.21362, -0.14, 0.24, 0.142773, 0.909661},
77 {-0.5, 0.866025, 0, 0, 0, 0},
78 {0.6, -0.11547, 0.791623, 0, 0, 0},
80 {-0.04, -0.138564, 0.540662, -0.18, 0.809003, 0},
81 {-0.25, -0.606218, -0.240013, 0.26, -0.231685, 0.625392},
96 {0, 0, -0.7, 0.714143, 0, 0},
97 {0, 0, 0.66, -0.123225, 0.741091, 0},
98 {0, 0, 0.47, 0.152631, -0.393194, 0.775373},
110 {1, 0, 0, 0, 0, 0, 0},
111 {0, 1, 0, 0, 0, 0, 0},
112 {-0.4, -0.4, 0.824621, 0, 0, 0, 0},
113 {-0.5, 0, 0.242536, 0.83137, 0, 0, 0},
114 {-0.5, -0.2, 0.630593, -0.484671, 0.278293, 0, 0},
115 {0, 0, -0.242536, 0.672172, 0.642214, 0.27735, 0},
116 {-0.8, 0, -0.388057, -0.367926, 0.238537, -3.58949e-15, 0.130931},
130 {-0.4, 0.916515, 0, 0, 0, 0},
131 {-0.6, 0.174574, 0.78072, 0, 0, 0},
132 {0, 0.654654, 0.365963, 0.661438, 0, 0},
133 {0, -0.545545, 0.762422, 0.118114, 0.327327, 0},
134 {-0.4, -0.174574, -0.396459, 0.392138, 0.49099, 0.507445},
147 {-0.5, 0.866025, 0, 0, 0, 0},
148 {0.2, 0.57735, 0.791623, 0, 0, 0},
149 {0, 0.46188, -0.336861, 0.820482, 0, 0},
150 {0, -0.69282, 0.252646, 0.493742, 0.460857, 0},
151 {0, -0.23094, 0.16843, 0.808554, -0.220827, 0.464515},
164 {1, 0, 0, 0, 0, 0, 0},
165 {0.5, 0.866025, 0, 0, 0, 0, 0},
166 {-0.4, -0.57735, 0.711805, 0, 0, 0, 0},
167 {-0.5, 0.057735, 0.468293, 0.726201, 0, 0, 0},
168 {-0.4, -0.11547, 0.805464, -0.23482, 0.350363, 0, 0},
169 {0, 0, 0, 0.688514, 0.461454, 0.559471, 0},
170 {0, 0, 0.280976, 0.231921, -0.490509, 0.11916, 0.782603},
184 {-0.7, 0.714143, 0, 0, 0, 0},
186 {-0.4, 0.168034, 0, 0.90098, 0, 0},
187 {0, -0.70014, 0.5, 0.130577, 0.4927, 0},
188 {0, 0, 0.5, 0.221981, -0.566238, 0.616522},
201 {-0.5, 0.866025, 0, 0, 0, 0},
202 {0.2, 0.57735, 0.791623, 0, 0, 0},
203 {0, 0.46188, -0.336861, 0.820482, 0, 0},
204 {0, -0.69282, 0.252646, 0.493742, 0.460857, 0},
205 {0, -0.23094, 0.16843, 0.808554, -0.220827, 0.464515},
217 {1, 0, 0, 0, 0, 0, 0},
218 {0.5, 0.866025, 0, 0, 0, 0, 0},
219 {-0.8, -0.11547, 0.588784, 0, 0, 0, 0},
220 {-0.4, 0.23094, 0.520847, 0.717903, 0, 0, 0},
221 {-0.5, 0.288675, 0.73598, -0.348236, 0.0610847, 0, 0},
222 {0.2, -0.11547, 0.418943, 0.541106, 0.219905, 0.655744, 0},
223 {0.3, -0.057735, 0.73598, -0.348236, 0.0610847, -0.304997, 0.383375},
237 {-0.5, 0.866025, 0, 0, 0, 0},
238 {0, 0.46188, 0.886942, 0, 0, 0},
239 {-0.4, -0.23094, 0.120263, 0.878751, 0, 0},
240 {0, -0.311769, 0.55697, -0.249198, 0.728344, 0},
241 {0, -0.069282, 0.295397, 0.430696, 0.468462, 0.709214},
247 m_uniformRv = CreateObject<UniformRandomVariable> ();
251 m_normalRv = CreateObject<NormalRandomVariable> ();
277 static TypeId tid =
TypeId (
"ns3::ThreeGppChannelModel")
280 .AddConstructor<ThreeGppChannelModel> ()
281 .AddAttribute (
"Frequency",
282 "The operating Frequency in Hz",
286 MakeDoubleChecker<double> ())
287 .AddAttribute (
"Scenario",
288 "The 3GPP scenario (RMa, UMa, UMi-StreetCanyon, InH-OfficeOpen, InH-OfficeMixed)",
293 .AddAttribute (
"ChannelConditionModel",
294 "Pointer to the channel condition model",
298 MakePointerChecker<ChannelConditionModel> ())
299 .AddAttribute (
"UpdatePeriod",
300 "Specify the channel coherence time",
305 .AddAttribute (
"Blockage",
306 "Enable blockage model A (sec 7.6.4.1)",
310 .AddAttribute (
"NumNonselfBlocking",
311 "number of non-self-blocking regions",
314 MakeIntegerChecker<uint16_t> ())
315 .AddAttribute (
"PortraitMode",
316 "true for portrait mode, false for landscape mode",
320 .AddAttribute (
"BlockerSpeed",
321 "The speed of moving blockers, the unit is m/s",
324 MakeDoubleChecker<double> ())
325 .AddAttribute (
"vScatt",
326 "Maximum speed of the vehicle in the layout (see 3GPP TR 37.885 v15.3.0, Sec. 6.2.3)."
327 "Used to compute the additional contribution for the Doppler of"
328 "delayed (reflected) paths",
331 MakeDoubleChecker<double> (0.0))
355 NS_ASSERT_MSG (
f >= 500.0e6 &&
f <= 100.0e9,
"Frequency should be between 0.5 and 100 GHz but is " <<
f);
370 NS_ASSERT_MSG (scenario ==
"RMa" || scenario ==
"UMa" || scenario ==
"UMi-StreetCanyon"
371 || scenario ==
"InH-OfficeOpen" || scenario ==
"InH-OfficeMixed"
372 || scenario ==
"V2V-Urban" || scenario ==
"V2V-Highway",
373 "Unknown scenario, choose between: RMa, UMa, UMi-StreetCanyon, "
374 "InH-OfficeOpen, InH-OfficeMixed, V2V-Urban or V2V-Highway");
387 double hUT,
double distance2D)
const
398 bool los = channelCondition->IsLos ();
399 bool o2i = channelCondition->IsO2i ();
408 table3gpp->m_numOfCluster = 11;
409 table3gpp->m_raysPerCluster = 20;
410 table3gpp->m_uLgDS = -7.49;
411 table3gpp->m_sigLgDS = 0.55;
412 table3gpp->m_uLgASD = 0.90;
413 table3gpp->m_sigLgASD = 0.38;
414 table3gpp->m_uLgASA = 1.52;
415 table3gpp->m_sigLgASA = 0.24;
416 table3gpp->m_uLgZSA = 0.47;
417 table3gpp->m_sigLgZSA = 0.40;
418 table3gpp->m_uLgZSD = 0.34;
419 table3gpp->m_sigLgZSD =
std::max (-1.0, -0.17 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.22);
420 table3gpp->m_offsetZOD = 0;
421 table3gpp->m_cDS = 3.91e-9;
422 table3gpp->m_cASD = 2;
423 table3gpp->m_cASA = 3;
424 table3gpp->m_cZSA = 3;
426 table3gpp->m_sigK = 4;
427 table3gpp->m_rTau = 3.8;
428 table3gpp->m_uXpr = 12;
429 table3gpp->m_sigXpr = 4;
430 table3gpp->m_perClusterShadowingStd = 3;
432 for (uint8_t row = 0; row < 7; row++)
434 for (uint8_t column = 0; column < 7; column++)
436 table3gpp->m_sqrtC[row][column] =
sqrtC_RMa_LOS[row][column];
440 else if (!los && !o2i)
442 table3gpp->m_numOfCluster = 10;
443 table3gpp->m_raysPerCluster = 20;
444 table3gpp->m_uLgDS = -7.43;
445 table3gpp->m_sigLgDS = 0.48;
446 table3gpp->m_uLgASD = 0.95;
447 table3gpp->m_sigLgASD = 0.45;
448 table3gpp->m_uLgASA = 1.52;
449 table3gpp->m_sigLgASA = 0.13;
450 table3gpp->m_uLgZSA = 0.58;
451 table3gpp->m_sigLgZSA = 0.37;
452 table3gpp->m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
453 table3gpp->m_sigLgZSD = 0.30;
454 table3gpp->m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
455 table3gpp->m_cDS = 3.91e-9;
456 table3gpp->m_cASD = 2;
457 table3gpp->m_cASA = 3;
458 table3gpp->m_cZSA = 3;
460 table3gpp->m_sigK = 0;
461 table3gpp->m_rTau = 1.7;
462 table3gpp->m_uXpr = 7;
463 table3gpp->m_sigXpr = 3;
464 table3gpp->m_perClusterShadowingStd = 3;
466 for (uint8_t row = 0; row < 6; row++)
468 for (uint8_t column = 0; column < 6; column++)
476 table3gpp->m_numOfCluster = 10;
477 table3gpp->m_raysPerCluster = 20;
478 table3gpp->m_uLgDS = -7.47;
479 table3gpp->m_sigLgDS = 0.24;
480 table3gpp->m_uLgASD = 0.67;
481 table3gpp->m_sigLgASD = 0.18;
482 table3gpp->m_uLgASA = 1.66;
483 table3gpp->m_sigLgASA = 0.21;
484 table3gpp->m_uLgZSA = 0.93;
485 table3gpp->m_sigLgZSA = 0.22;
486 table3gpp->m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
487 table3gpp->m_sigLgZSD = 0.30;
488 table3gpp->m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
489 table3gpp->m_cDS = 3.91e-9;
490 table3gpp->m_cASD = 2;
491 table3gpp->m_cASA = 3;
492 table3gpp->m_cZSA = 3;
494 table3gpp->m_sigK = 0;
495 table3gpp->m_rTau = 1.7;
496 table3gpp->m_uXpr = 7;
497 table3gpp->m_sigXpr = 3;
498 table3gpp->m_perClusterShadowingStd = 3;
500 for (uint8_t row = 0; row < 6; row++)
502 for (uint8_t column = 0; column < 6; column++)
504 table3gpp->m_sqrtC[row][column] =
sqrtC_RMa_O2I[row][column];
513 table3gpp->m_numOfCluster = 12;
514 table3gpp->m_raysPerCluster = 20;
515 table3gpp->m_uLgDS = -6.955 - 0.0963 * log10 (fcGHz);
516 table3gpp->m_sigLgDS = 0.66;
517 table3gpp->m_uLgASD = 1.06 + 0.1114 * log10 (fcGHz);
518 table3gpp->m_sigLgASD = 0.28;
519 table3gpp->m_uLgASA = 1.81;
520 table3gpp->m_sigLgASA = 0.20;
521 table3gpp->m_uLgZSA = 0.95;
522 table3gpp->m_sigLgZSA = 0.16;
523 table3gpp->m_uLgZSD =
std::max (-0.5, -2.1 * distance2D / 1000 - 0.01 * (hUT - 1.5) + 0.75);
524 table3gpp->m_sigLgZSD = 0.40;
525 table3gpp->m_offsetZOD = 0;
526 table3gpp->m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;
527 table3gpp->m_cASD = 5;
528 table3gpp->m_cASA = 11;
529 table3gpp->m_cZSA = 7;
531 table3gpp->m_sigK = 3.5;
532 table3gpp->m_rTau = 2.5;
533 table3gpp->m_uXpr = 8;
534 table3gpp->m_sigXpr = 4;
535 table3gpp->m_perClusterShadowingStd = 3;
537 for (uint8_t row = 0; row < 7; row++)
539 for (uint8_t column = 0; column < 7; column++)
541 table3gpp->m_sqrtC[row][column] =
sqrtC_UMa_LOS[row][column];
547 double uLgZSD =
std::max (-0.5, -2.1 * distance2D / 1000 - 0.01 * (hUT - 1.5) + 0.9);
549 double afc = 0.208 * log10 (fcGHz) - 0.782;
551 double cfc = -0.13 * log10 (fcGHz) + 2.03;
552 double efc = 7.66 * log10 (fcGHz) - 5.96;
554 double offsetZOD = efc - std::pow (10, afc * log10 (
std::max (bfc, distance2D)) + cfc);
558 table3gpp->m_numOfCluster = 20;
559 table3gpp->m_raysPerCluster = 20;
560 table3gpp->m_uLgDS = -6.28 - 0.204 * log10 (fcGHz);
561 table3gpp->m_sigLgDS = 0.39;
562 table3gpp->m_uLgASD = 1.5 - 0.1144 * log10 (fcGHz);
563 table3gpp->m_sigLgASD = 0.28;
564 table3gpp->m_uLgASA = 2.08 - 0.27 * log10 (fcGHz);
565 table3gpp->m_sigLgASA = 0.11;
566 table3gpp->m_uLgZSA = -0.3236 * log10 (fcGHz) + 1.512;
567 table3gpp->m_sigLgZSA = 0.16;
568 table3gpp->m_uLgZSD = uLgZSD;
569 table3gpp->m_sigLgZSD = 0.49;
570 table3gpp->m_offsetZOD = offsetZOD;
571 table3gpp->m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;
572 table3gpp->m_cASD = 2;
573 table3gpp->m_cASA = 15;
574 table3gpp->m_cZSA = 7;
576 table3gpp->m_sigK = 0;
577 table3gpp->m_rTau = 2.3;
578 table3gpp->m_uXpr = 7;
579 table3gpp->m_sigXpr = 3;
580 table3gpp->m_perClusterShadowingStd = 3;
582 for (uint8_t row = 0; row < 6; row++)
584 for (uint8_t column = 0; column < 6; column++)
592 table3gpp->m_numOfCluster = 12;
593 table3gpp->m_raysPerCluster = 20;
594 table3gpp->m_uLgDS = -6.62;
595 table3gpp->m_sigLgDS = 0.32;
596 table3gpp->m_uLgASD = 1.25;
597 table3gpp->m_sigLgASD = 0.42;
598 table3gpp->m_uLgASA = 1.76;
599 table3gpp->m_sigLgASA = 0.16;
600 table3gpp->m_uLgZSA = 1.01;
601 table3gpp->m_sigLgZSA = 0.43;
602 table3gpp->m_uLgZSD = uLgZSD;
603 table3gpp->m_sigLgZSD = 0.49;
604 table3gpp->m_offsetZOD = offsetZOD;
605 table3gpp->m_cDS = 11e-9;
606 table3gpp->m_cASD = 5;
607 table3gpp->m_cASA = 8;
608 table3gpp->m_cZSA = 3;
610 table3gpp->m_sigK = 0;
611 table3gpp->m_rTau = 2.2;
612 table3gpp->m_uXpr = 9;
613 table3gpp->m_sigXpr = 5;
614 table3gpp->m_perClusterShadowingStd = 4;
616 for (uint8_t row = 0; row < 6; row++)
618 for (uint8_t column = 0; column < 6; column++)
620 table3gpp->m_sqrtC[row][column] =
sqrtC_UMa_O2I[row][column];
633 table3gpp->m_numOfCluster = 12;
634 table3gpp->m_raysPerCluster = 20;
635 table3gpp->m_uLgDS = -0.24 * log10 (1 + fcGHz) - 7.14;
636 table3gpp->m_sigLgDS = 0.38;
637 table3gpp->m_uLgASD = -0.05 * log10 (1 + fcGHz) + 1.21;
638 table3gpp->m_sigLgASD = 0.41;
639 table3gpp->m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.73;
640 table3gpp->m_sigLgASA = 0.014 * log10 (1 + fcGHz) + 0.28;
641 table3gpp->m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73;
642 table3gpp->m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34;
643 table3gpp->m_uLgZSD =
std::max (-0.21, -14.8 * distance2D / 1000 + 0.01 * std::abs (hUT - hBS) + 0.83);
644 table3gpp->m_sigLgZSD = 0.35;
645 table3gpp->m_offsetZOD = 0;
646 table3gpp->m_cDS = 5e-9;
647 table3gpp->m_cASD = 3;
648 table3gpp->m_cASA = 17;
649 table3gpp->m_cZSA = 7;
651 table3gpp->m_sigK = 5;
652 table3gpp->m_rTau = 3;
653 table3gpp->m_uXpr = 9;
654 table3gpp->m_sigXpr = 3;
655 table3gpp->m_perClusterShadowingStd = 3;
657 for (uint8_t row = 0; row < 7; row++)
659 for (uint8_t column = 0; column < 7; column++)
661 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_LOS[row][column];
667 double uLgZSD =
std::max (-0.5, -3.1 * distance2D / 1000 + 0.01 *
std::max (hUT - hBS, 0.0) + 0.2);
668 double offsetZOD = -1 * std::pow (10, -1.5 * log10 (
std::max (10.0, distance2D)) + 3.3);
671 table3gpp->m_numOfCluster = 19;
672 table3gpp->m_raysPerCluster = 20;
673 table3gpp->m_uLgDS = -0.24 * log10 (1 + fcGHz) - 6.83;
674 table3gpp->m_sigLgDS = 0.16 * log10 (1 + fcGHz) + 0.28;
675 table3gpp->m_uLgASD = -0.23 * log10 (1 + fcGHz) + 1.53;
676 table3gpp->m_sigLgASD = 0.11 * log10 (1 + fcGHz) + 0.33;
677 table3gpp->m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
678 table3gpp->m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
679 table3gpp->m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
680 table3gpp->m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
681 table3gpp->m_uLgZSD = uLgZSD;
682 table3gpp->m_sigLgZSD = 0.35;
683 table3gpp->m_offsetZOD = offsetZOD;
684 table3gpp->m_cDS = 11e-9;
685 table3gpp->m_cASD = 10;
686 table3gpp->m_cASA = 22;
687 table3gpp->m_cZSA = 7;
689 table3gpp->m_sigK = 0;
690 table3gpp->m_rTau = 2.1;
691 table3gpp->m_uXpr = 8;
692 table3gpp->m_sigXpr = 3;
693 table3gpp->m_perClusterShadowingStd = 3;
695 for (uint8_t row = 0; row < 6; row++)
697 for (uint8_t column = 0; column < 6; column++)
705 table3gpp->m_numOfCluster = 12;
706 table3gpp->m_raysPerCluster = 20;
707 table3gpp->m_uLgDS = -6.62;
708 table3gpp->m_sigLgDS = 0.32;
709 table3gpp->m_uLgASD = 1.25;
710 table3gpp->m_sigLgASD = 0.42;
711 table3gpp->m_uLgASA = 1.76;
712 table3gpp->m_sigLgASA = 0.16;
713 table3gpp->m_uLgZSA = 1.01;
714 table3gpp->m_sigLgZSA = 0.43;
715 table3gpp->m_uLgZSD = uLgZSD;
716 table3gpp->m_sigLgZSD = 0.35;
717 table3gpp->m_offsetZOD = offsetZOD;
718 table3gpp->m_cDS = 11e-9;
719 table3gpp->m_cASD = 5;
720 table3gpp->m_cASA = 8;
721 table3gpp->m_cZSA = 3;
723 table3gpp->m_sigK = 0;
724 table3gpp->m_rTau = 2.2;
725 table3gpp->m_uXpr = 9;
726 table3gpp->m_sigXpr = 5;
727 table3gpp->m_perClusterShadowingStd = 4;
729 for (uint8_t row = 0; row < 6; row++)
731 for (uint8_t column = 0; column < 6; column++)
733 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_O2I[row][column];
741 NS_ASSERT_MSG (!o2i,
"The indoor scenario does out support outdoor to indoor");
744 table3gpp->m_numOfCluster = 15;
745 table3gpp->m_raysPerCluster = 20;
746 table3gpp->m_uLgDS = -0.01 * log10 (1 + fcGHz) - 7.692;
747 table3gpp->m_sigLgDS = 0.18;
748 table3gpp->m_uLgASD = 1.60;
749 table3gpp->m_sigLgASD = 0.18;
750 table3gpp->m_uLgASA = -0.19 * log10 (1 + fcGHz) + 1.781;
751 table3gpp->m_sigLgASA = 0.12 * log10 (1 + fcGHz) + 0.119;
752 table3gpp->m_uLgZSA = -0.26 * log10 (1 + fcGHz) + 1.44;
753 table3gpp->m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.264;
754 table3gpp->m_uLgZSD = -1.43 * log10 (1 + fcGHz) + 2.228;
755 table3gpp->m_sigLgZSD = 0.13 * log10 (1 + fcGHz) + 0.30;
756 table3gpp->m_offsetZOD = 0;
757 table3gpp->m_cDS = 3.91e-9;
758 table3gpp->m_cASD = 5;
759 table3gpp->m_cASA = 8;
760 table3gpp->m_cZSA = 9;
762 table3gpp->m_sigK = 4;
763 table3gpp->m_rTau = 3.6;
764 table3gpp->m_uXpr = 11;
765 table3gpp->m_sigXpr = 4;
766 table3gpp->m_perClusterShadowingStd = 6;
768 for (uint8_t row = 0; row < 7; row++)
770 for (uint8_t column = 0; column < 7; column++)
778 table3gpp->m_numOfCluster = 19;
779 table3gpp->m_raysPerCluster = 20;
780 table3gpp->m_uLgDS = -0.28 * log10 (1 + fcGHz) - 7.173;
781 table3gpp->m_sigLgDS = 0.1 * log10 (1 + fcGHz) + 0.055;
782 table3gpp->m_uLgASD = 1.62;
783 table3gpp->m_sigLgASD = 0.25;
784 table3gpp->m_uLgASA = -0.11 * log10 (1 + fcGHz) + 1.863;
785 table3gpp->m_sigLgASA = 0.12 * log10 (1 + fcGHz) + 0.059;
786 table3gpp->m_uLgZSA = -0.15 * log10 (1 + fcGHz) + 1.387;
787 table3gpp->m_sigLgZSA = -0.09 * log10 (1 + fcGHz) + 0.746;
788 table3gpp->m_uLgZSD = 1.08;
789 table3gpp->m_sigLgZSD = 0.36;
790 table3gpp->m_offsetZOD = 0;
791 table3gpp->m_cDS = 3.91e-9;
792 table3gpp->m_cASD = 5;
793 table3gpp->m_cASA = 11;
794 table3gpp->m_cZSA = 9;
796 table3gpp->m_sigK = 0;
797 table3gpp->m_rTau = 3;
798 table3gpp->m_uXpr = 10;
799 table3gpp->m_sigXpr = 4;
800 table3gpp->m_perClusterShadowingStd = 3;
802 for (uint8_t row = 0; row < 6; row++)
804 for (uint8_t column = 0; column < 6; column++)
813 if (channelCondition->IsLos ())
817 table3gpp->m_numOfCluster = 12;
818 table3gpp->m_raysPerCluster = 20;
819 table3gpp->m_uLgDS = -0.2 * log10 (1 + fcGHz) - 7.5;
820 table3gpp->m_sigLgDS = 0.1;
821 table3gpp->m_uLgASD = -0.1 * log10 (1 + fcGHz) + 1.6;
822 table3gpp->m_sigLgASD = 0.1;
823 table3gpp->m_uLgASA = -0.1 * log10 (1 + fcGHz) + 1.6;
824 table3gpp->m_sigLgASA = 0.1;
825 table3gpp->m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73;
826 table3gpp->m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34;
827 table3gpp->m_uLgZSD = -0.1 * log10 (1 + fcGHz) + 0.73;
828 table3gpp->m_sigLgZSD = -0.04 * log10 (1 + fcGHz) + 0.34;
829 table3gpp->m_offsetZOD = 0;
830 table3gpp->m_cDS = 5;
831 table3gpp->m_cASD = 17;
832 table3gpp->m_cASA = 17;
833 table3gpp->m_cZSA = 7;
834 table3gpp->m_uK = 3.48;
835 table3gpp->m_sigK = 2;
836 table3gpp->m_rTau = 3;
837 table3gpp->m_uXpr = 9;
838 table3gpp->m_sigXpr = 3;
839 table3gpp->m_perClusterShadowingStd = 4;
841 for (uint8_t row = 0; row < 7; row++)
843 for (uint8_t column = 0; column < 7; column++)
845 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_LOS[row][column];
849 else if (channelCondition->IsNlos ())
851 table3gpp->m_numOfCluster = 19;
852 table3gpp->m_raysPerCluster = 20;
853 table3gpp->m_uLgDS = -0.3 * log10 (1 + fcGHz) - 7;
854 table3gpp->m_sigLgDS = 0.28;
855 table3gpp->m_uLgASD = -0.08 * log10 (1 + fcGHz) + 1.81;
856 table3gpp->m_sigLgASD = 0.05 * log10 (1 + fcGHz) + 0.3;
857 table3gpp->m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
858 table3gpp->m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
859 table3gpp->m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
860 table3gpp->m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
861 table3gpp->m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
862 table3gpp->m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
863 table3gpp->m_offsetZOD = 0;
864 table3gpp->m_cDS = 11;
865 table3gpp->m_cASD = 22;
866 table3gpp->m_cASA = 22;
867 table3gpp->m_cZSA = 7;
869 table3gpp->m_sigK = 0;
870 table3gpp->m_rTau = 2.1;
871 table3gpp->m_uXpr = 8;
872 table3gpp->m_sigXpr = 3;
873 table3gpp->m_perClusterShadowingStd = 4;
875 for (uint8_t row = 0; row < 6; row++)
877 for (uint8_t column = 0; column < 6; column++)
883 else if (channelCondition->IsNlosv ())
885 table3gpp->m_numOfCluster = 19;
886 table3gpp->m_raysPerCluster = 20;
887 table3gpp->m_uLgDS = -0.4 * log10 (1 + fcGHz) - 7;
888 table3gpp->m_sigLgDS = 0.1;
889 table3gpp->m_uLgASD = -0.1 * log10 (1 + fcGHz) + 1.7;
890 table3gpp->m_sigLgASD = 0.1;
891 table3gpp->m_uLgASA = -0.1 * log10 (1 + fcGHz) + 1.7;
892 table3gpp->m_sigLgASA = 0.1;
893 table3gpp->m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
894 table3gpp->m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
895 table3gpp->m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
896 table3gpp->m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
897 table3gpp->m_offsetZOD = 0;
898 table3gpp->m_cDS = 11;
899 table3gpp->m_cASD = 22;
900 table3gpp->m_cASA = 22;
901 table3gpp->m_cZSA = 7;
903 table3gpp->m_sigK = 4.5;
904 table3gpp->m_rTau = 2.1;
905 table3gpp->m_uXpr = 8;
906 table3gpp->m_sigXpr = 3;
907 table3gpp->m_perClusterShadowingStd = 4;
909 for (uint8_t row = 0; row < 6; row++)
911 for (uint8_t column = 0; column < 6; column++)
913 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_LOS[row][column];
924 if (channelCondition->IsLos ())
926 table3gpp->m_numOfCluster = 12;
927 table3gpp->m_raysPerCluster = 20;
928 table3gpp->m_uLgDS = -8.3;
929 table3gpp->m_sigLgDS = 0.2;
930 table3gpp->m_uLgASD = 1.4;
931 table3gpp->m_sigLgASD = 0.1;
932 table3gpp->m_uLgASA = 1.4;
933 table3gpp->m_sigLgASA = 0.1;
934 table3gpp->m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73;
935 table3gpp->m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34;
936 table3gpp->m_uLgZSD = -0.1 * log10 (1 + fcGHz) + 0.73;
937 table3gpp->m_sigLgZSD = -0.04 * log10 (1 + fcGHz) + 0.34;
938 table3gpp->m_offsetZOD = 0;
939 table3gpp->m_cDS = 5;
940 table3gpp->m_cASD = 17;
941 table3gpp->m_cASA = 17;
942 table3gpp->m_cZSA = 7;
944 table3gpp->m_sigK = 3.5;
945 table3gpp->m_rTau = 3;
946 table3gpp->m_uXpr = 9;
947 table3gpp->m_sigXpr = 3;
948 table3gpp->m_perClusterShadowingStd = 4;
950 for (uint8_t row = 0; row < 7; row++)
952 for (uint8_t column = 0; column < 7; column++)
954 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_LOS[row][column];
958 else if (channelCondition->IsNlosv ())
960 table3gpp->m_numOfCluster = 19;
961 table3gpp->m_raysPerCluster = 20;
962 table3gpp->m_uLgDS = -8.3;
963 table3gpp->m_sigLgDS = 0.3;
964 table3gpp->m_uLgASD = 1.5;
965 table3gpp->m_sigLgASD = 0.1;
966 table3gpp->m_uLgASA = 1.5;
967 table3gpp->m_sigLgASA = 0.1;
968 table3gpp->m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
969 table3gpp->m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
970 table3gpp->m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
971 table3gpp->m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
972 table3gpp->m_offsetZOD = 0;
973 table3gpp->m_cDS = 11;
974 table3gpp->m_cASD = 22;
975 table3gpp->m_cASA = 22;
976 table3gpp->m_cZSA = 7;
978 table3gpp->m_sigK = 4.5;
979 table3gpp->m_rTau = 2.1;
980 table3gpp->m_uXpr = 8.0;
981 table3gpp->m_sigXpr = 3;
982 table3gpp->m_perClusterShadowingStd = 4;
984 for (uint8_t row = 0; row < 6; row++)
986 for (uint8_t column = 0; column < 6; column++)
988 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_LOS[row][column];
992 else if (channelCondition->IsNlos ())
994 NS_LOG_WARN (
"The fast fading parameters for the NLOS condition in the Highway scenario are not defined in TR 37.885, use the ones defined in TDoc R1-1803671 instead");
996 table3gpp->m_numOfCluster = 19;
997 table3gpp->m_raysPerCluster = 20;
998 table3gpp->m_uLgDS = -0.3 * log10 (1 + fcGHz) - 7;
999 table3gpp->m_sigLgDS = 0.28;
1000 table3gpp->m_uLgASD = -0.08 * log10 (1 + fcGHz) + 1.81;
1001 table3gpp->m_sigLgASD = 0.05 * log10 (1 + fcGHz) + 0.3;
1002 table3gpp->m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
1003 table3gpp->m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
1004 table3gpp->m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
1005 table3gpp->m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
1006 table3gpp->m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
1007 table3gpp->m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
1008 table3gpp->m_offsetZOD = 0;
1009 table3gpp->m_cDS = 11;
1010 table3gpp->m_cASD = 22;
1011 table3gpp->m_cASA = 22;
1012 table3gpp->m_cZSA = 7;
1013 table3gpp->m_uK = 0;
1014 table3gpp->m_sigK = 0;
1015 table3gpp->m_rTau = 2.1;
1016 table3gpp->m_uXpr = 8;
1017 table3gpp->m_sigXpr = 3;
1018 table3gpp->m_perClusterShadowingStd = 4;
1020 for (uint8_t row = 0; row < 6; row++)
1022 for (uint8_t column = 0; column < 6; column++)
1047 bool update =
false;
1050 if (!channelCondition->IsEqual (channelParams->m_losCondition, channelParams->m_o2iCondition))
1071 if (channelParams->m_generatedTime > channelMatrix->m_generatedTime)
1092 uint64_t channelMatrixKey =
GetKey (aAntenna->GetId (), bAntenna->GetId ());
1099 bool updateParams =
false;
1100 bool updateMatrix =
false;
1101 bool notFoundParams =
false;
1102 bool notFoundMatrix =
false;
1116 notFoundParams =
true;
1119 double x = aMob->GetPosition ().x - bMob->GetPosition ().x;
1120 double y = aMob->GetPosition ().y - bMob->GetPosition ().y;
1121 double distance2D = sqrt (
x *
x + y * y);
1125 double hUt =
std::min (aMob->GetPosition ().z, bMob->GetPosition ().z);
1126 double hBs =
std::max (aMob->GetPosition ().z, bMob->GetPosition ().z);
1131 if (notFoundParams || updateParams)
1156 notFoundMatrix =
true;
1161 if (notFoundMatrix || updateMatrix)
1164 channelMatrix =
GetNewChannel (channelParams, table3gpp, aMob, bMob, aAntenna, bAntenna);
1165 channelMatrix->
m_antennaPair = std::make_pair (aAntenna->GetId (), bAntenna->GetId ());
1171 return channelMatrix;
1189 NS_LOG_WARN (
"Channel params map not found. Returning a nullptr.");
1206 channelParams->m_nodeIds = std::make_pair (aMob->GetObject<
Node> ()->
GetId (), bMob->GetObject<
Node> ()->
GetId ());
1207 channelParams->m_losCondition = channelCondition->GetLosCondition ();
1208 channelParams->m_o2iCondition = channelCondition->GetO2iCondition ();
1212 uint8_t paramNum = 6;
1219 for (uint8_t iter = 0; iter < paramNum; iter++)
1221 LSPsIndep.push_back (
m_normalRv->GetValue ());
1223 for (uint8_t row = 0; row < paramNum; row++)
1226 for (uint8_t column = 0; column < paramNum; column++)
1228 temp += table3gpp->m_sqrtC[row][column] * LSPsIndep[column];
1230 LSPs.push_back (temp);
1234 double DS, ASD, ASA, ZSA, ZSD, kFactor = 0;
1237 kFactor = LSPs[1] * table3gpp->m_sigK + table3gpp->m_uK;
1238 DS = pow (10, LSPs[2] * table3gpp->m_sigLgDS + table3gpp->m_uLgDS);
1239 ASD = pow (10, LSPs[3] * table3gpp->m_sigLgASD + table3gpp->m_uLgASD);
1240 ASA = pow (10, LSPs[4] * table3gpp->m_sigLgASA + table3gpp->m_uLgASA);
1241 ZSD = pow (10, LSPs[5] * table3gpp->m_sigLgZSD + table3gpp->m_uLgZSD);
1242 ZSA = pow (10, LSPs[6] * table3gpp->m_sigLgZSA + table3gpp->m_uLgZSA);
1246 DS = pow (10, LSPs[1] * table3gpp->m_sigLgDS + table3gpp->m_uLgDS);
1247 ASD = pow (10, LSPs[2] * table3gpp->m_sigLgASD + table3gpp->m_uLgASD);
1248 ASA = pow (10, LSPs[3] * table3gpp->m_sigLgASA + table3gpp->m_uLgASA);
1249 ZSD = pow (10, LSPs[4] * table3gpp->m_sigLgZSD + table3gpp->m_uLgZSD);
1250 ZSA = pow (10, LSPs[5] * table3gpp->m_sigLgZSA + table3gpp->m_uLgZSA);
1259 channelParams->m_DS = DS;
1260 channelParams->m_K_factor = kFactor;
1262 NS_LOG_INFO (
"K-factor=" << kFactor <<
", DS=" << DS <<
", ASD=" << ASD <<
", ASA=" << ASA
1263 <<
", ZSD=" << ZSD <<
", ZSA=" << ZSA);
1267 double minTau = 100.0;
1268 for (uint8_t cIndex = 0; cIndex < table3gpp->m_numOfCluster; cIndex++)
1275 clusterDelay.push_back (tau);
1278 for (uint8_t cIndex = 0; cIndex < table3gpp->m_numOfCluster; cIndex++)
1280 clusterDelay[cIndex] -= minTau;
1282 std::sort (clusterDelay.begin (), clusterDelay.end ());
1289 double powerSum = 0;
1290 for (uint8_t cIndex = 0; cIndex < table3gpp->m_numOfCluster; cIndex++)
1292 double power = exp (-1 * clusterDelay[cIndex] * (table3gpp->m_rTau - 1) / table3gpp->m_rTau / DS) *
1293 pow (10, -1 *
m_normalRv->GetValue () * table3gpp->m_perClusterShadowingStd / 10);
1295 clusterPower.push_back (power);
1297 channelParams->m_clusterPower = clusterPower;
1299 double powerMax = 0;
1301 for (uint8_t cIndex = 0; cIndex < table3gpp->m_numOfCluster; cIndex++)
1303 channelParams->m_clusterPower[cIndex] = channelParams->m_clusterPower[cIndex] / powerSum;
1309 double kLinear = pow (10, kFactor / 10);
1311 for (uint8_t cIndex = 0; cIndex < table3gpp->m_numOfCluster; cIndex++)
1315 clusterPowerForAngles.push_back (channelParams->m_clusterPower[cIndex] / (1 + kLinear) +
1316 kLinear / (1 + kLinear));
1320 clusterPowerForAngles.push_back (channelParams->m_clusterPower[cIndex] / (1 + kLinear));
1322 if (powerMax < clusterPowerForAngles[cIndex])
1324 powerMax = clusterPowerForAngles[cIndex];
1330 for (uint8_t cIndex = 0; cIndex < table3gpp->m_numOfCluster; cIndex++)
1332 clusterPowerForAngles.push_back (channelParams->m_clusterPower[cIndex]);
1333 if (powerMax < clusterPowerForAngles[cIndex])
1335 powerMax = clusterPowerForAngles[cIndex];
1342 double thresh = 0.0032;
1343 for (uint8_t cIndex = table3gpp->m_numOfCluster; cIndex > 0; cIndex--)
1345 if (clusterPowerForAngles[cIndex - 1] < thresh * powerMax )
1347 clusterPowerForAngles.erase (clusterPowerForAngles.begin () + cIndex - 1);
1348 channelParams->m_clusterPower.erase (channelParams->m_clusterPower.begin () + cIndex - 1);
1349 clusterDelay.erase (clusterDelay.begin () + cIndex - 1);
1353 NS_ASSERT (channelParams->m_clusterPower.size () < UINT8_MAX);
1354 channelParams->m_reducedClusterNumber = channelParams->m_clusterPower.size ();
1358 double cTau = 0.7705 - 0.0433 * kFactor + 2e-4 * pow (kFactor,2) + 17e-6 * pow (kFactor,3);
1359 for (uint8_t cIndex = 0; cIndex < channelParams->m_reducedClusterNumber; cIndex++)
1361 clusterDelay[cIndex] = clusterDelay[cIndex] / cTau;
1370 switch (table3gpp->m_numOfCluster)
1409 double cPhi = cNlos;
1413 cPhi *= (1.1035 - 0.028 * kFactor - 2e-3 * pow (kFactor, 2) + 1e-4 * pow (kFactor, 3));
1416 switch (table3gpp->m_numOfCluster)
1443 double cTheta = cNlos;
1444 if (channelCondition->IsLos())
1446 cTheta *= (1.3086 + 0.0339 * kFactor - 0.0077 * pow (kFactor, 2) + 2e-4 * pow (kFactor, 3));
1449 DoubleVector clusterAoa, clusterAod, clusterZoa, clusterZod;
1450 for (uint8_t cIndex = 0; cIndex < channelParams->m_reducedClusterNumber; cIndex++)
1452 double logCalc = -1 * log (clusterPowerForAngles[cIndex] / powerMax);
1453 double angle = 2 * sqrt (logCalc) / 1.4 / cPhi;
1454 clusterAoa.push_back (ASA * angle);
1455 clusterAod.push_back (ASD * angle);
1456 angle = logCalc / cTheta;
1457 clusterZoa.push_back (ZSA * angle);
1458 clusterZod.push_back (ZSD * angle);
1461 Angles sAngle (bMob->GetPosition (), aMob->GetPosition ());
1462 Angles uAngle (aMob->GetPosition (), bMob->GetPosition ());
1464 for (uint8_t cIndex = 0; cIndex < channelParams->m_reducedClusterNumber; cIndex++)
1473 if (channelCondition->IsO2i ())
1475 clusterZoa[cIndex] = clusterZoa[cIndex] * Xn + (
m_normalRv->GetValue () * ZSA / 7) + 90;
1493 for (uint8_t cIndex = 0; cIndex < channelParams->m_reducedClusterNumber; cIndex++)
1495 clusterAoa[cIndex] -= diffAoa;
1496 clusterAod[cIndex] -= diffAod;
1497 clusterZoa[cIndex] -= diffZsa;
1498 clusterZod[cIndex] -= diffZsd;
1502 double sizeTemp = clusterZoa.size ();
1503 for (uint8_t ind = 0; ind < 4; ind++)
1509 angleDegree = clusterAoa;
1512 angleDegree = clusterZoa;
1515 angleDegree = clusterAod;
1518 angleDegree = clusterZod;
1523 for (uint8_t nIndex = 0; nIndex < sizeTemp; nIndex++)
1525 while (angleDegree[nIndex] > 360)
1527 angleDegree[nIndex] -= 360;
1530 while (angleDegree[nIndex] < 0)
1532 angleDegree[nIndex] += 360;
1535 if (ind == 1 || ind == 3)
1537 if (angleDegree[nIndex] > 180)
1539 angleDegree[nIndex] = 360 - angleDegree[nIndex];
1546 clusterAoa = angleDegree;
1549 clusterZoa = angleDegree;
1552 clusterAod = angleDegree;
1555 clusterZod = angleDegree;
1566 for (uint8_t cInd = 0; cInd < channelParams->m_reducedClusterNumber; cInd++)
1568 channelParams->m_clusterPower[cInd] = channelParams->m_clusterPower[cInd] / pow (10,attenuationDb[cInd] / 10);
1573 attenuationDb.push_back (0);
1577 channelParams->m_attenuation_dB = attenuationDb;
1586 for (uint8_t nInd = 0; nInd < channelParams->m_reducedClusterNumber; nInd++)
1588 for (uint8_t mInd = 0; mInd < table3gpp->m_raysPerCluster; mInd++)
1590 double tempAoa = clusterAoa[nInd] + table3gpp->m_cASA *
offSetAlpha[mInd];
1591 double tempZoa = clusterZoa[nInd] + table3gpp->m_cZSA *
offSetAlpha[mInd];
1594 double tempAod = clusterAod[nInd] + table3gpp->m_cASD *
offSetAlpha[mInd];
1595 double tempZod = clusterZod[nInd] + 0.375 * pow (10,table3gpp->m_uLgZSD) *
offSetAlpha[mInd];
1600 for (uint8_t cIndex = 0; cIndex < channelParams->m_reducedClusterNumber; cIndex++)
1602 Shuffle (&rayAodRadian[cIndex][0], &rayAodRadian[cIndex][table3gpp->m_raysPerCluster]);
1603 Shuffle (&rayAoaRadian[cIndex][0], &rayAoaRadian[cIndex][table3gpp->m_raysPerCluster]);
1604 Shuffle (&rayZodRadian[cIndex][0], &rayZodRadian[cIndex][table3gpp->m_raysPerCluster]);
1605 Shuffle (&rayZoaRadian[cIndex][0], &rayZoaRadian[cIndex][table3gpp->m_raysPerCluster]);
1609 channelParams->m_rayAodRadian = rayAodRadian;
1610 channelParams->m_rayAoaRadian = rayAoaRadian;
1611 channelParams->m_rayZodRadian = rayZodRadian;
1612 channelParams->m_rayZoaRadian = rayZoaRadian;
1618 for (uint8_t nInd = 0; nInd < channelParams->m_reducedClusterNumber; nInd++)
1622 for (uint8_t mInd = 0; mInd < table3gpp->m_raysPerCluster; mInd++)
1624 double uXprLinear = pow (10, table3gpp->m_uXpr / 10);
1625 double sigXprLinear = pow (10, table3gpp->m_sigXpr / 10);
1627 temp.push_back (std::pow (10, (
m_normalRv->GetValue () * sigXprLinear + uXprLinear) / 10));
1629 for (uint8_t pInd = 0; pInd < 4; pInd++)
1633 temp2.push_back (temp3);
1635 crossPolarizationPowerRatios.push_back (temp);
1636 clusterPhase.push_back (temp2);
1639 channelParams->m_clusterPhase = clusterPhase;
1640 channelParams->m_crossPolarizationPowerRatios = crossPolarizationPowerRatios;
1642 uint8_t cluster1st = 0, cluster2nd = 0;
1643 double maxPower = 0;
1644 for (uint8_t cIndex = 0; cIndex < channelParams->m_reducedClusterNumber; cIndex++)
1646 if (maxPower < channelParams->m_clusterPower[cIndex])
1648 maxPower = channelParams->m_clusterPower[cIndex];
1649 cluster1st = cIndex;
1652 channelParams->m_cluster1st = cluster1st;
1654 for (uint8_t cIndex = 0; cIndex < channelParams->m_reducedClusterNumber; cIndex++)
1656 if (maxPower < channelParams->m_clusterPower[cIndex] && cluster1st != cIndex)
1658 maxPower = channelParams->m_clusterPower[cIndex];
1659 cluster2nd = cIndex;
1662 channelParams->m_cluster2nd = cluster2nd;
1664 NS_LOG_INFO (
"1st strongest cluster:" << +cluster1st
1665 <<
", 2nd strongest cluster:" << +cluster2nd);
1668 if (cluster1st == cluster2nd)
1670 clusterDelay.push_back (clusterDelay[cluster1st] + 1.28 * table3gpp->m_cDS);
1671 clusterDelay.push_back (clusterDelay[cluster1st] + 2.56 * table3gpp->m_cDS);
1673 clusterAoa.push_back (clusterAoa[cluster1st]);
1674 clusterAoa.push_back (clusterAoa[cluster1st]);
1676 clusterZoa.push_back (clusterZoa[cluster1st]);
1677 clusterZoa.push_back (clusterZoa[cluster1st]);
1679 clusterAod.push_back (clusterAod[cluster1st]);
1680 clusterAod.push_back (clusterAod[cluster1st]);
1682 clusterZod.push_back (clusterZod[cluster1st]);
1683 clusterZod.push_back (clusterZod[cluster1st]);
1688 if (cluster1st < cluster2nd)
1698 clusterDelay.push_back (clusterDelay[
min] + 1.28 * table3gpp->m_cDS);
1699 clusterDelay.push_back (clusterDelay[
min] + 2.56 * table3gpp->m_cDS);
1700 clusterDelay.push_back (clusterDelay[
max] + 1.28 * table3gpp->m_cDS);
1701 clusterDelay.push_back (clusterDelay[
max] + 2.56 * table3gpp->m_cDS);
1703 clusterAoa.push_back (clusterAoa[
min]);
1704 clusterAoa.push_back (clusterAoa[
min]);
1705 clusterAoa.push_back (clusterAoa[
max]);
1706 clusterAoa.push_back (clusterAoa[
max]);
1708 clusterZoa.push_back (clusterZoa[
min]);
1709 clusterZoa.push_back (clusterZoa[
min]);
1710 clusterZoa.push_back (clusterZoa[
max]);
1711 clusterZoa.push_back (clusterZoa[
max]);
1713 clusterAod.push_back (clusterAod[
min]);
1714 clusterAod.push_back (clusterAod[
min]);
1715 clusterAod.push_back (clusterAod[
max]);
1716 clusterAod.push_back (clusterAod[
max]);
1718 clusterZod.push_back (clusterZod[
min]);
1719 clusterZod.push_back (clusterZod[
min]);
1720 clusterZod.push_back (clusterZod[
max]);
1721 clusterZod.push_back (clusterZod[
max]);
1726 channelParams->m_delay = clusterDelay;
1727 channelParams->m_angle.clear ();
1728 channelParams->m_angle.push_back (clusterAoa);
1729 channelParams->m_angle.push_back (clusterZoa);
1730 channelParams->m_angle.push_back (clusterAod);
1731 channelParams->m_angle.push_back (clusterZod);
1747 uint8_t updatedClusterNumber = (channelParams->m_reducedClusterNumber == 1) ? channelParams->m_reducedClusterNumber + 2 : channelParams->m_reducedClusterNumber + 4;
1749 for (uint8_t cIndex = 0; cIndex < updatedClusterNumber ; cIndex++)
1758 dopplerTermAlpha.push_back (
alpha);
1759 dopplerTermD.push_back (D);
1761 channelParams->m_alpha = dopplerTermAlpha;
1762 channelParams->m_D = dopplerTermD;
1764 return channelParams;
1786 bool isSameDirection = (channelParams->m_nodeIds == channelMatrix->
m_nodeIds);
1797 if (isSameDirection)
1799 rayAodRadian = channelParams->m_rayAodRadian;
1800 rayAoaRadian = channelParams->m_rayAoaRadian;
1801 rayZodRadian = channelParams->m_rayZodRadian;
1802 rayZoaRadian = channelParams->m_rayZoaRadian;
1806 rayAodRadian = channelParams->m_rayAoaRadian;
1807 rayAoaRadian = channelParams->m_rayAodRadian;
1808 rayZodRadian = channelParams->m_rayZoaRadian;
1809 rayZoaRadian = channelParams->m_rayZodRadian;
1818 uint64_t uSize = uAntenna->GetNumberOfElements ();
1819 uint64_t sSize = sAntenna->GetNumberOfElements ();
1821 hUsn.resize (uSize);
1822 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1824 hUsn[uIndex].resize (sSize);
1825 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1827 hUsn[uIndex][sIndex].resize (channelParams->m_reducedClusterNumber);
1831 NS_ASSERT (channelParams->m_reducedClusterNumber <= channelParams->m_clusterPhase.size ());
1832 NS_ASSERT (channelParams->m_reducedClusterNumber <= channelParams->m_clusterPower.size ());
1833 NS_ASSERT (channelParams->m_reducedClusterNumber <= channelParams->m_crossPolarizationPowerRatios.size ());
1834 NS_ASSERT (channelParams->m_reducedClusterNumber <= rayZoaRadian.size ());
1835 NS_ASSERT (channelParams->m_reducedClusterNumber <= rayZodRadian.size ());
1836 NS_ASSERT (channelParams->m_reducedClusterNumber <= rayAoaRadian.size ());
1837 NS_ASSERT (channelParams->m_reducedClusterNumber <= rayAodRadian.size ());
1838 NS_ASSERT (table3gpp->m_raysPerCluster <= channelParams->m_clusterPhase[0].size ());
1839 NS_ASSERT (table3gpp->m_raysPerCluster <= channelParams->m_crossPolarizationPowerRatios[0].size ());
1840 NS_ASSERT (table3gpp->m_raysPerCluster <= rayZoaRadian[0].size ());
1841 NS_ASSERT (table3gpp->m_raysPerCluster <= rayZodRadian[0].size ());
1842 NS_ASSERT (table3gpp->m_raysPerCluster <= rayAoaRadian[0].size ());
1843 NS_ASSERT (table3gpp->m_raysPerCluster <= rayAodRadian[0].size ());
1846 double x = sMob->GetPosition ().x - uMob->GetPosition ().x;
1847 double y = sMob->GetPosition ().y - uMob->GetPosition ().y;
1848 double distance2D = sqrt (
x *
x + y * y);
1851 double hUt =
std::min (sMob->GetPosition ().z, uMob->GetPosition ().z);
1852 double hBs =
std::max (sMob->GetPosition ().z, uMob->GetPosition ().z);
1854 double distance3D = std::sqrt (distance2D * distance2D + (hBs - hUt) * (hBs - hUt));
1856 Angles sAngle (uMob->GetPosition (), sMob->GetPosition ());
1857 Angles uAngle (sMob->GetPosition (), uMob->GetPosition ());
1861 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1863 Vector uLoc = uAntenna->GetElementLocation (uIndex);
1865 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1867 Vector sLoc = sAntenna->GetElementLocation (sIndex);
1869 for (uint8_t nIndex = 0; nIndex < channelParams->m_reducedClusterNumber; nIndex++)
1873 if (nIndex != channelParams->m_cluster1st && nIndex != channelParams->m_cluster2nd)
1875 std::complex<double> rays (0,0);
1876 for (uint8_t mIndex = 0; mIndex < table3gpp->m_raysPerCluster; mIndex++)
1878 DoubleVector initialPhase = channelParams->m_clusterPhase[nIndex][mIndex];
1879 double k = channelParams->m_crossPolarizationPowerRatios[nIndex][mIndex];
1881 double rxPhaseDiff = 2 * M_PI * (sin (rayZoaRadian[nIndex][mIndex]) * cos (rayAoaRadian[nIndex][mIndex]) * uLoc.x
1882 + sin (rayZoaRadian[nIndex][mIndex]) * sin (rayAoaRadian[nIndex][mIndex]) * uLoc.y
1883 + cos (rayZoaRadian[nIndex][mIndex]) * uLoc.z);
1885 double txPhaseDiff = 2 * M_PI * (sin (rayZodRadian[nIndex][mIndex]) * cos (rayAodRadian[nIndex][mIndex]) * sLoc.x
1886 + sin (rayZodRadian[nIndex][mIndex]) * sin (rayAodRadian[nIndex][mIndex]) * sLoc.y
1887 + cos (rayZodRadian[nIndex][mIndex]) * sLoc.z);
1890 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1891 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (channelParams->m_rayAoaRadian[nIndex][mIndex], channelParams->m_rayZoaRadian[nIndex][mIndex]));
1892 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (channelParams->m_rayAodRadian[nIndex][mIndex], channelParams->m_rayZodRadian[nIndex][mIndex]));
1894 rays += (std::complex<double> (cos (initialPhase[0]), sin (initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1895 std::complex<double> (cos (initialPhase[1]), sin (initialPhase[1])) * std::sqrt (1 /
k) * rxFieldPatternTheta * txFieldPatternPhi +
1896 std::complex<double> (cos (initialPhase[2]), sin (initialPhase[2])) * std::sqrt (1 /
k) * rxFieldPatternPhi * txFieldPatternTheta +
1897 std::complex<double> (cos (initialPhase[3]), sin (initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1898 * std::complex<double> (cos (rxPhaseDiff), sin (rxPhaseDiff))
1899 * std::complex<double> (cos (txPhaseDiff), sin (txPhaseDiff));
1901 rays *= sqrt (channelParams->m_clusterPower[nIndex] / table3gpp->m_raysPerCluster);
1902 hUsn[uIndex][sIndex][nIndex] = rays;
1906 std::complex<double> raysSub1 (0, 0);
1907 std::complex<double> raysSub2 (0, 0);
1908 std::complex<double> raysSub3 (0, 0);
1910 for (uint8_t mIndex = 0; mIndex < table3gpp->m_raysPerCluster; mIndex++)
1912 double k = channelParams->m_crossPolarizationPowerRatios[nIndex][mIndex];
1915 DoubleVector initialPhase = channelParams->m_clusterPhase[nIndex][mIndex];
1918 double rxPhaseDiff = 2 * M_PI * (sin (rayZoaRadian[nIndex][mIndex]) * cos (rayAoaRadian[nIndex][mIndex]) * uLoc.x
1919 + sin (rayZoaRadian[nIndex][mIndex]) * sin (rayAoaRadian[nIndex][mIndex]) * uLoc.y
1920 + cos (rayZoaRadian[nIndex][mIndex]) * uLoc.z);
1921 double txPhaseDiff = 2 * M_PI * (sin (rayZodRadian[nIndex][mIndex]) * cos (rayAodRadian[nIndex][mIndex]) * sLoc.x
1922 + sin (rayZodRadian[nIndex][mIndex]) * sin (rayAodRadian[nIndex][mIndex]) * sLoc.y
1923 + cos (rayZodRadian[nIndex][mIndex]) * sLoc.z);
1925 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1926 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (rayAoaRadian[nIndex][mIndex], rayZoaRadian[nIndex][mIndex]));
1927 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (rayAodRadian[nIndex][mIndex], rayZodRadian[nIndex][mIndex]));
1929 std::complex<double> raySub = (std::complex<double> (cos (initialPhase[0]), sin (initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1930 std::complex<double> (cos (initialPhase[1]), sin (initialPhase[1])) * sqrt (1 /
k) * rxFieldPatternTheta * txFieldPatternPhi +
1931 std::complex<double> (cos (initialPhase[2]), sin (initialPhase[2])) * sqrt (1 /
k) * rxFieldPatternPhi * txFieldPatternTheta +
1932 std::complex<double> (cos (initialPhase[3]), sin (initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1933 * std::complex<double> (cos (rxPhaseDiff), sin (rxPhaseDiff))
1934 * std::complex<double> (cos (txPhaseDiff), sin (txPhaseDiff));
1957 raysSub1 *= sqrt (channelParams->m_clusterPower[nIndex] / table3gpp->m_raysPerCluster);
1958 raysSub2 *= sqrt (channelParams->m_clusterPower[nIndex] / table3gpp->m_raysPerCluster);
1959 raysSub3 *= sqrt (channelParams->m_clusterPower[nIndex] / table3gpp->m_raysPerCluster);
1960 hUsn[uIndex][sIndex][nIndex] = raysSub1;
1961 hUsn[uIndex][sIndex].push_back (raysSub2);
1962 hUsn[uIndex][sIndex].push_back (raysSub3);
1968 std::complex<double> ray (0, 0);
1976 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1982 ray = (rxFieldPatternTheta * txFieldPatternTheta - rxFieldPatternPhi * txFieldPatternPhi)
1983 * std::complex<double> (cos (-2 * M_PI * distance3D / lambda), sin (-2 * M_PI * distance3D / lambda))
1984 * std::complex<double> (cos (rxPhaseDiff), sin (rxPhaseDiff))
1985 * std::complex<double> (cos (txPhaseDiff), sin (txPhaseDiff));
1987 double kLinear = pow (10, channelParams->m_K_factor / 10);
1989 hUsn[uIndex][sIndex][0] = sqrt (1 / (kLinear + 1)) * hUsn[uIndex][sIndex][0] + sqrt (kLinear / (1 + kLinear)) * ray / pow (10, channelParams->m_attenuation_dB[0] / 10);
1990 double tempSize = hUsn[uIndex][sIndex].size ();
1991 for (uint8_t nIndex = 1; nIndex < tempSize; nIndex++)
1993 hUsn[uIndex][sIndex][nIndex] *= sqrt (1 / (kLinear + 1));
1999 NS_LOG_DEBUG (
"Husn (sAntenna, uAntenna):" << sAntenna->GetId () <<
", " << uAntenna->GetId ());
2010 NS_LOG_INFO (
"size of coefficient matrix =[" << hUsn.size () <<
"][" << hUsn[0].size () <<
"][" << hUsn[0][0].size () <<
"]");
2012 return channelMatrix;
2015 std::pair<double, double>
2018 inclinationRad =
WrapTo2Pi (inclinationRad);
2019 if (inclinationRad > M_PI)
2022 inclinationRad -= M_PI;
2028 NS_ASSERT_MSG (0 <= inclinationRad && inclinationRad <= M_PI,
2029 "inclinationRad=" << inclinationRad <<
" not valid, should be in [0, pi]");
2031 "azimuthRad=" << azimuthRad <<
" not valid, should be in [0, 2*pi]");
2033 return std::make_pair (azimuthRad, inclinationRad);
2044 uint8_t clusterNum = clusterAOA.size ();
2045 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
2047 powerAttenuation.push_back (0);
2057 double thetaSb = 110;
2068 if (channelParams->m_nonSelfBlocking.size () == 0)
2078 table.push_back (90);
2080 table.push_back (2);
2085 table.push_back (90);
2086 table.push_back (5);
2087 table.push_back (10);
2089 channelParams->m_nonSelfBlocking.push_back (table);
2094 double deltaX = sqrt (pow (channelParams->m_preLocUT.x - channelParams->m_locUT.x, 2) + pow (channelParams->m_preLocUT.y - channelParams->m_locUT.y, 2));
2120 R = exp (-1 * (deltaX / corrDis + (
Now ().GetSeconds () - channelParams->m_generatedTime.GetSeconds ()) / corrT));
2124 R = exp (-1 * (deltaX / corrDis));
2128 <<
" Time difference:" <<
Now ().GetSeconds () - channelParams->m_generatedTime.GetSeconds ()
2129 <<
" correlation:" << R);
2138 if (R * R * (-0.069) + R * 1.074 - 0.002 < 1)
2140 R = R * R * (-0.069) + R * 1.074 - 0.002;
2146 channelParams->m_nonSelfBlocking[blockInd][
PHI_INDEX] =
2147 R * channelParams->m_nonSelfBlocking[blockInd][
PHI_INDEX] + sqrt (1 - R * R) *
m_normalRv->GetValue ();
2154 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
2156 NS_ASSERT_MSG (clusterAOA[cInd] >= 0 && clusterAOA[cInd] <= 360,
"the AOA should be the range of [0,360]");
2157 NS_ASSERT_MSG (clusterZOA[cInd] >= 0 && clusterZOA[cInd] <= 180,
"the ZOA should be the range of [0,180]");
2160 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phiSb - xSb / 2 <<
","
2161 << phiSb + xSb / 2 <<
"]");
2162 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << thetaSb - ySb / 2 <<
","
2163 << thetaSb + ySb / 2 <<
"]");
2164 if (std::abs (clusterAOA[cInd] - phiSb) < (xSb / 2)
2165 && std::abs (clusterZOA[cInd] - thetaSb) < (ySb / 2))
2167 powerAttenuation[cInd] += 30;
2168 NS_LOG_INFO (
"Cluster[" << +cInd <<
"] is blocked by self blocking region and reduce 30 dB power,"
2169 "the attenuation is [" << powerAttenuation[cInd] <<
" dB]");
2176 double phiK = (0.5 * erfc (-1 * channelParams->m_nonSelfBlocking[blockInd][
PHI_INDEX] / sqrt (2))) * 360;
2187 double xK = channelParams->m_nonSelfBlocking[blockInd][
X_INDEX];
2188 double thetaK = channelParams->m_nonSelfBlocking[blockInd][
THETA_INDEX];
2189 double yK = channelParams->m_nonSelfBlocking[blockInd][
Y_INDEX];
2191 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phiK - xK <<
"," << phiK + xK <<
"]");
2192 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << thetaK - yK <<
"," << thetaK + yK <<
"]");
2194 if ( std::abs (clusterAOA[cInd] - phiK) < (xK)
2195 && std::abs (clusterZOA[cInd] - thetaK) < (yK))
2197 double A1 = clusterAOA[cInd] - (phiK + xK / 2);
2198 double A2 = clusterAOA[cInd] - (phiK - xK / 2);
2199 double Z1 = clusterZOA[cInd] - (thetaK + yK / 2);
2200 double Z2 = clusterZOA[cInd] - (thetaK - yK / 2);
2201 int signA1, signA2, signZ1, signZ2;
2203 if (xK / 2 < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= xK)
2211 if (-1 * xK < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= -1 * xK / 2)
2220 if (yK / 2 < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= yK)
2228 if (-1 * yK < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= -1 * yK / 2)
2237 double fA1 = atan (signA1 * M_PI / 2 * sqrt (M_PI / lambda *
2239 double fA2 = atan (signA2 * M_PI / 2 * sqrt (M_PI / lambda *
2241 double fZ1 = atan (signZ1 * M_PI / 2 * sqrt (M_PI / lambda *
2243 double fZ2 = atan (signZ2 * M_PI / 2 * sqrt (M_PI / lambda *
2245 double lDb = -20 * log10 (1 - (fA1 + fA2) * (fZ1 + fZ2));
2246 powerAttenuation[cInd] += lDb;
2247 NS_LOG_INFO (
"Cluster[" << +cInd <<
"] is blocked by no-self blocking, the loss is ["
2252 return powerAttenuation;
2258 for (
auto i = (last -
first) - 1; i > 0; --i)
double f(double x, void *params)
Class holding the azimuth and inclination angles of spherical coordinates.
double GetInclination(void) const
Getter for inclination angle.
double GetAzimuth(void) const
Getter for azimuth angle.
AttributeValue implementation for Boolean.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Hold a signed integer type.
This is an interface for a channel model that can be described by a channel matrix,...
std::vector< Complex2DVector > Complex3DVector
type definition for complex 3D matrices
std::vector< DoubleVector > Double2DVector
type definition for matrices of doubles
std::vector< double > DoubleVector
type definition for vectors of doubles
static uint64_t GetKey(uint32_t a, uint32_t b)
Generate a unique value for the pair of unsigned integer of 32 bits, where the order does not matter,...
std::vector< Double2DVector > Double3DVector
type definition for 3D matrices of doubles
uint32_t GetId(void) const
Hold objects of type Ptr<T>.
Smart pointer class similar to boost::intrusive_ptr.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static Time Now(void)
Return the current simulation virtual time.
Hold variables of type string.
DoubleVector CalcAttenuationOfBlockage(const Ptr< ThreeGppChannelModel::ThreeGppChannelParams > channelParams, const DoubleVector &clusterAOA, const DoubleVector &clusterZOA) const
Applies the blockage model A described in 3GPP TR 38.901.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
bool m_portraitMode
true if potrait mode, false if landscape
bool ChannelParamsNeedsUpdate(Ptr< const ThreeGppChannelParams > channelParams, Ptr< const ChannelCondition > channelCondition) const
Check if the channel params has to be updated.
virtual Ptr< const ParamsTable > GetThreeGppTable(Ptr< const ChannelCondition > channelCondition, double hBS, double hUT, double distance2D) const
Get the parameters needed to apply the channel generation procedure.
Ptr< NormalRandomVariable > m_normalRv
normal random variable
static const uint8_t Y_INDEX
index of the Y value in the m_nonSelfBlocking array
bool m_blockage
enables the blockage model A
Ptr< const ChannelParams > GetParams(Ptr< const MobilityModel > aMob, Ptr< const MobilityModel > bMob) const override
Looks for the channel params associated to the aMob and bMob pair in m_channelParamsMap.
~ThreeGppChannelModel()
Destructor.
bool ChannelMatrixNeedsUpdate(Ptr< const ThreeGppChannelParams > channelParams, Ptr< const ChannelMatrix > channelMatrix)
Check if the channel matrix has to be updated (it needs update when the channel params generation tim...
static const uint8_t THETA_INDEX
index of the THETA value in the m_nonSelfBlocking array
std::unordered_map< uint64_t, Ptr< ThreeGppChannelParams > > m_channelParamsMap
map containing the common channel parameters per pair of nodes, the key of this map is reciprocal and...
static std::pair< double, double > WrapAngles(double azimuthRad, double inclinationRad)
Wrap an (azimuth, inclination) angle pair in a valid range.
ThreeGppChannelModel()
Constructor.
double m_blockerSpeed
the blocker speed
Ptr< const ChannelMatrix > GetChannel(Ptr< const MobilityModel > aMob, Ptr< const MobilityModel > bMob, Ptr< const PhasedArrayModel > aAntenna, Ptr< const PhasedArrayModel > bAntenna) override
Looks for the channel matrix associated to the aMob and bMob pair in m_channelMatrixMap.
void SetFrequency(double f)
Sets the center frequency of the model.
std::unordered_map< uint64_t, Ptr< ChannelMatrix > > m_channelMatrixMap
map containing the channel realizations per pair of PhasedAntennaArray instances, the key of this map...
Ptr< UniformRandomVariable > m_uniformRv
uniform random variable
void DoDispose() override
Destructor implementation.
void SetScenario(const std::string &scenario)
Sets the propagation scenario.
void SetChannelConditionModel(Ptr< ChannelConditionModel > model)
Set the channel condition model.
Ptr< UniformRandomVariable > m_uniformRvDoppler
uniform random variable, used to compute the additional Doppler contribution
uint16_t m_numNonSelfBlocking
number of non-self-blocking regions
virtual Ptr< ChannelMatrix > GetNewChannel(Ptr< const ThreeGppChannelParams > channelParams, Ptr< const ParamsTable > table3gpp, const Ptr< const MobilityModel > sMob, const Ptr< const MobilityModel > uMob, Ptr< const PhasedArrayModel > sAntenna, Ptr< const PhasedArrayModel > uAntenna) const
Compute the channel matrix between two nodes a and b, and their antenna arrays aAntenna and bAntenna ...
static const uint8_t PHI_INDEX
index of the PHI value in the m_nonSelfBlocking array
double m_frequency
the operating frequency
double m_vScatt
value used to compute the additional Doppler contribution for the delayed paths
Ptr< ChannelConditionModel > GetChannelConditionModel() const
Get the associated channel condition model.
Ptr< ChannelConditionModel > m_channelConditionModel
the channel condition model
std::string m_scenario
the 3GPP scenario
std::string GetScenario(void) const
Returns the propagation scenario.
static const uint8_t R_INDEX
index of the R value in the m_nonSelfBlocking array
double GetFrequency(void) const
Returns the center frequency.
static TypeId GetTypeId()
Get the type ID.
void Shuffle(double *first, double *last) const
Shuffle the elements of a simple sequence container of type double.
Ptr< ThreeGppChannelParams > GenerateChannelParameters(const Ptr< const ChannelCondition > channelCondition, const Ptr< const ParamsTable > table3gpp, const Ptr< const MobilityModel > aMob, const Ptr< const MobilityModel > bMob) const
Prepare 3gpp channel parameters among the nodes a and b.
Time m_updatePeriod
the channel update period
static const uint8_t X_INDEX
index of the X value in the m_nonSelfBlocking array
Ptr< UniformRandomVariable > m_uniformRvShuffle
uniform random variable used to shuffle array in GetNewChannel
bool IsZero(void) const
Exactly equivalent to t == 0.
AttributeValue implementation for Time.
a unique identifier for an interface.
TypeId SetGroupName(std::string groupName)
Set the group name.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeStringAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeChecker > MakeStringChecker(void)
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static const double offSetAlpha[20]
The ray offset angles within a cluster, given for rms angle spread normalized to 1....
static const double sqrtC_RMa_O2I[6][6]
The square root matrix for RMa O2I, which is generated using the Cholesky decomposition according to ...
static const double sqrtC_UMi_LOS[7][7]
The square root matrix for UMi LOS, which is generated using the Cholesky decomposition according to ...
static const double sqrtC_office_LOS[7][7]
The square root matrix for Indoor-Office LOS, which is generated using the Cholesky decomposition acc...
static const double sqrtC_UMa_O2I[6][6]
The square root matrix for UMa O2I, which is generated using the Cholesky decomposition according to ...
static const double sqrtC_RMa_NLOS[6][6]
The square root matrix for RMa NLOS, which is generated using the Cholesky decomposition according to...
static const double sqrtC_UMa_LOS[7][7]
The square root matrix for UMa LOS, which is generated using the Cholesky decomposition according to ...
static const double sqrtC_UMi_NLOS[6][6]
The square root matrix for UMi NLOS, which is generated using the Cholesky decomposition according to...
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
static const double sqrtC_RMa_LOS[7][7]
The square root matrix for RMa LOS, which is generated using the Cholesky decomposition according to ...
double DegreesToRadians(double degrees)
converts degrees to radians
void swap(UUID &uuid1, UUID &uuid2) noexcept
static const double sqrtC_UMi_O2I[6][6]
The square root matrix for UMi O2I, which is generated using the Cholesky decomposition according to ...
static const double sqrtC_office_NLOS[6][6]
The square root matrix for Indoor-Office NLOS, which is generated using the Cholesky decomposition ac...
static const double sqrtC_UMa_NLOS[6][6]
The square root matrix for UMa NLOS, which is generated using the Cholesky decomposition according to...
double WrapTo2Pi(double a)
Wrap angle in [0, 2*M_PI)
double RadiansToDegrees(double radians)
converts radians to degrees
float alpha
Plot alpha value (transparency)
list x
Random number samples.
Complex3DVector m_channel
channel matrix H[u][s][n].
std::pair< uint32_t, uint32_t > m_antennaPair
the first element is the ID of the antenna of the s-node (the antenna of the transmitter when the cha...
Time m_generatedTime
generation time
std::pair< uint32_t, uint32_t > m_nodeIds
the first element is the s-node ID (the transmitter when the channel was generated),...