25 #include "ns3/three-gpp-antenna-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,0.6797,-0.6797,0.8844,-0.8844,1.1481,-1.1481,1.5195,-1.5195,2.1551,-2.1551
59 {1, 0, 0, 0, 0, 0, 0},
60 {0, 1, 0, 0, 0, 0, 0},
61 {-0.5, 0, 0.866025, 0, 0, 0, 0},
62 {0, 0, 0, 1, 0, 0, 0},
63 {0, 0, 0, 0, 1, 0, 0},
64 {0.01, 0, -0.0519615, 0.73, -0.2, 0.651383, 0},
65 {-0.17, -0.02, 0.21362, -0.14, 0.24, 0.142773, 0.909661},
70 {-0.5, 0.866025, 0, 0, 0, 0},
71 {0.6, -0.11547, 0.791623, 0, 0, 0},
73 {-0.04, -0.138564, 0.540662, -0.18, 0.809003, 0},
74 {-0.25, -0.606218, -0.240013, 0.26, -0.231685, 0.625392},
81 {0, 0, -0.7, 0.714143, 0, 0},
82 {0, 0, 0.66, -0.123225, 0.741091, 0},
83 {0, 0, 0.47, 0.152631, -0.393194, 0.775373},
87 {1, 0, 0, 0, 0, 0, 0},
88 {0, 1, 0, 0, 0, 0, 0},
89 {-0.4, -0.4, 0.824621, 0, 0, 0, 0},
90 {-0.5, 0, 0.242536, 0.83137, 0, 0, 0},
91 {-0.5, -0.2, 0.630593, -0.484671, 0.278293, 0, 0},
92 {0, 0, -0.242536, 0.672172, 0.642214, 0.27735, 0},
93 {-0.8, 0, -0.388057, -0.367926, 0.238537, -3.58949e-15, 0.130931},
99 {-0.4, 0.916515, 0, 0, 0, 0},
100 {-0.6, 0.174574, 0.78072, 0, 0, 0},
101 {0, 0.654654, 0.365963, 0.661438, 0, 0},
102 {0, -0.545545, 0.762422, 0.118114, 0.327327, 0},
103 {-0.4, -0.174574, -0.396459, 0.392138, 0.49099, 0.507445},
108 {-0.5, 0.866025, 0, 0, 0, 0},
109 {0.2, 0.57735, 0.791623, 0, 0, 0},
110 {0, 0.46188, -0.336861, 0.820482, 0, 0},
111 {0, -0.69282, 0.252646, 0.493742, 0.460857, 0},
112 {0, -0.23094, 0.16843, 0.808554, -0.220827, 0.464515},
117 {1, 0, 0, 0, 0, 0, 0},
118 {0.5, 0.866025, 0, 0, 0, 0, 0},
119 {-0.4, -0.57735, 0.711805, 0, 0, 0, 0},
120 {-0.5, 0.057735, 0.468293, 0.726201, 0, 0, 0},
121 {-0.4, -0.11547, 0.805464, -0.23482, 0.350363, 0, 0},
122 {0, 0, 0, 0.688514, 0.461454, 0.559471, 0},
123 {0, 0, 0.280976, 0.231921, -0.490509, 0.11916, 0.782603},
128 {-0.7, 0.714143, 0, 0, 0, 0},
130 {-0.4, 0.168034, 0, 0.90098, 0, 0},
131 {0, -0.70014, 0.5, 0.130577, 0.4927, 0},
132 {0, 0, 0.5, 0.221981, -0.566238, 0.616522},
137 {-0.5, 0.866025, 0, 0, 0, 0},
138 {0.2, 0.57735, 0.791623, 0, 0, 0},
139 {0, 0.46188, -0.336861, 0.820482, 0, 0},
140 {0, -0.69282, 0.252646, 0.493742, 0.460857, 0},
141 {0, -0.23094, 0.16843, 0.808554, -0.220827, 0.464515},
145 {1, 0, 0, 0, 0, 0, 0},
146 {0.5, 0.866025, 0, 0, 0, 0, 0},
147 {-0.8, -0.11547, 0.588784, 0, 0, 0, 0},
148 {-0.4, 0.23094, 0.520847, 0.717903, 0, 0, 0},
149 {-0.5, 0.288675, 0.73598, -0.348236, 0.0610847, 0, 0},
150 {0.2, -0.11547, 0.418943, 0.541106, 0.219905, 0.655744, 0},
151 {0.3, -0.057735, 0.73598, -0.348236, 0.0610847, -0.304997, 0.383375},
156 {-0.5, 0.866025, 0, 0, 0, 0},
157 {0, 0.46188, 0.886942, 0, 0, 0},
158 {-0.4, -0.23094, 0.120263, 0.878751, 0, 0},
159 {0, -0.311769, 0.55697, -0.249198, 0.728344, 0},
160 {0, -0.069282, 0.295397, 0.430696, 0.468462, 0.709214},
166 m_uniformRv = CreateObject<UniformRandomVariable> ();
169 m_normalRv = CreateObject<NormalRandomVariable> ();
190 static TypeId tid =
TypeId (
"ns3::ThreeGppChannelModel")
192 .SetGroupName (
"Spectrum")
194 .AddConstructor<ThreeGppChannelModel> ()
195 .AddAttribute (
"Frequency",
196 "The operating Frequency in Hz",
200 MakeDoubleChecker<double> ())
201 .AddAttribute (
"Scenario",
202 "The 3GPP scenario (RMa, UMa, UMi-StreetCanyon, InH-OfficeOpen, InH-OfficeMixed)",
207 .AddAttribute (
"ChannelConditionModel",
208 "Pointer to the channel condition model",
212 MakePointerChecker<ChannelConditionModel> ())
213 .AddAttribute (
"UpdatePeriod",
214 "Specify the channel coherence time",
219 .AddAttribute (
"Blockage",
220 "Enable blockage model A (sec 7.6.4.1)",
224 .AddAttribute (
"NumNonselfBlocking",
225 "number of non-self-blocking regions",
228 MakeIntegerChecker<uint16_t> ())
229 .AddAttribute (
"PortraitMode",
230 "true for portrait mode, false for landscape mode",
234 .AddAttribute (
"BlockerSpeed",
235 "The speed of moving blockers, the unit is m/s",
238 MakeDoubleChecker<double> ())
261 NS_ASSERT_MSG (
f >= 500.0e6 &&
f <= 100.0e9,
"Frequency should be between 0.5 and 100 GHz but is " <<
f);
276 NS_ASSERT_MSG (scenario ==
"RMa" || scenario ==
"UMa" || scenario ==
"UMi-StreetCanyon" 277 || scenario ==
"InH-OfficeOpen" || scenario ==
"InH-OfficeMixed" 278 || scenario ==
"V2V-Urban" || scenario ==
"V2V-Highway",
279 "Unknown scenario, choose between RMa, UMa, UMi-StreetCanyon," 280 "InH-OfficeOpen, InH-OfficeMixed, V2V-Urban or V2V-Highway");
303 bool los = channelCondition->IsLos ();
304 bool o2i = channelCondition->IsO2i ();
324 table3gpp->
m_sigLgZSD =
std::max (-1.0, -0.17 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.22);
326 table3gpp->
m_cDS = 3.91e-9;
337 for (uint8_t row = 0; row < 7; row++)
339 for (uint8_t column = 0; column < 7; column++)
345 else if (!los && !o2i)
357 table3gpp->
m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
359 table3gpp->
m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
360 table3gpp->
m_cDS = 3.91e-9;
371 for (uint8_t row = 0; row < 6; row++)
373 for (uint8_t column = 0; column < 6; column++)
391 table3gpp->
m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
393 table3gpp->
m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
394 table3gpp->
m_cDS = 3.91e-9;
405 for (uint8_t row = 0; row < 6; row++)
407 for (uint8_t column = 0; column < 6; column++)
420 table3gpp->
m_uLgDS = -6.955 - 0.0963 * log10 (fcGHz);
422 table3gpp->
m_uLgASD = 1.06 + 0.1114 * log10 (fcGHz);
428 table3gpp->
m_uLgZSD =
std::max (-0.5, -2.1 * distance2D / 1000 - 0.01 * (hUT - 1.5) + 0.75);
431 table3gpp->
m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;
442 for (uint8_t row = 0; row < 7; row++)
444 for (uint8_t column = 0; column < 7; column++)
452 double uLgZSD =
std::max (-0.5, -2.1 * distance2D / 1000 - 0.01 * (hUT - 1.5) + 0.9);
454 double afc = 0.208 * log10 (fcGHz) - 0.782;
456 double cfc = -0.13 * log10 (fcGHz) + 2.03;
457 double efc = 7.66 * log10 (fcGHz) - 5.96;
459 double offsetZOD = efc - std::pow (10, afc * log10 (
std::max (bfc,distance2D)) + cfc);
465 table3gpp->
m_uLgDS = -6.28 - 0.204 * log10 (fcGHz);
467 table3gpp->
m_uLgASD = 1.5 - 0.1144 * log10 (fcGHz);
469 table3gpp->
m_uLgASA = 2.08 - 0.27 * log10 (fcGHz);
471 table3gpp->
m_uLgZSA = -0.3236 * log10 (fcGHz) + 1.512;
476 table3gpp->
m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;
487 for (uint8_t row = 0; row < 6; row++)
489 for (uint8_t column = 0; column < 6; column++)
510 table3gpp->
m_cDS = 11e-9;
521 for (uint8_t row = 0; row < 6; row++)
523 for (uint8_t column = 0; column < 6; column++)
540 table3gpp->
m_uLgDS = -0.24 * log10 (1 + fcGHz) - 7.14;
542 table3gpp->
m_uLgASD = -0.05 * log10 (1 + fcGHz) + 1.21;
544 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.73;
545 table3gpp->
m_sigLgASA = 0.014 * log10 (1 + fcGHz) + 0.28;
546 table3gpp->
m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73;
547 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34;
548 table3gpp->
m_uLgZSD =
std::max (-0.21, -14.8 * distance2D / 1000 + 0.01 * std::abs (hUT - hBS) + 0.83);
551 table3gpp->
m_cDS = 5e-9;
562 for (uint8_t row = 0; row < 7; row++)
564 for (uint8_t column = 0; column < 7; column++)
572 double uLgZSD =
std::max (-0.5, -3.1 * distance2D / 1000 + 0.01 *
std::max (hUT - hBS,0.0) + 0.2);
573 double offsetZOD = -1 * std::pow (10, -1.5 * log10 (
std::max (10.0, distance2D)) + 3.3);
578 table3gpp->
m_uLgDS = -0.24 * log10 (1 + fcGHz) - 6.83;
579 table3gpp->
m_sigLgDS = 0.16 * log10 (1 + fcGHz) + 0.28;
580 table3gpp->
m_uLgASD = -0.23 * log10 (1 + fcGHz) + 1.53;
581 table3gpp->
m_sigLgASD = 0.11 * log10 (1 + fcGHz) + 0.33;
582 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
583 table3gpp->
m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
584 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
585 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
589 table3gpp->
m_cDS = 11e-9;
600 for (uint8_t row = 0; row < 6; row++)
602 for (uint8_t column = 0; column < 6; column++)
623 table3gpp->
m_cDS = 11e-9;
634 for (uint8_t row = 0; row < 6; row++)
636 for (uint8_t column = 0; column < 6; column++)
646 NS_ASSERT_MSG (!o2i,
"The indoor scenario does out support outdoor to indoor");
651 table3gpp->
m_uLgDS = -0.01 * log10 (1 + fcGHz) - 7.692;
655 table3gpp->
m_uLgASA = -0.19 * log10 (1 + fcGHz) + 1.781;
656 table3gpp->
m_sigLgASA = 0.12 * log10 (1 + fcGHz) + 0.119;
657 table3gpp->
m_uLgZSA = -0.26 * log10 (1 + fcGHz) + 1.44;
658 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.264;
659 table3gpp->
m_uLgZSD = -1.43 * log10 (1 + fcGHz) + 2.228;
660 table3gpp->
m_sigLgZSD = 0.13 * log10 (1 + fcGHz) + 0.30;
662 table3gpp->
m_cDS = 3.91e-9;
673 for (uint8_t row = 0; row < 7; row++)
675 for (uint8_t column = 0; column < 7; column++)
685 table3gpp->
m_uLgDS = -0.28 * log10 (1 + fcGHz) - 7.173;
686 table3gpp->
m_sigLgDS = 0.1 * log10 (1 + fcGHz) + 0.055;
689 table3gpp->
m_uLgASA = -0.11 * log10 (1 + fcGHz) + 1.863;
690 table3gpp->
m_sigLgASA = 0.12 * log10 (1 + fcGHz) + 0.059;
691 table3gpp->
m_uLgZSA = -0.15 * log10 (1 + fcGHz) + 1.387;
692 table3gpp->
m_sigLgZSA = -0.09 * log10 (1 + fcGHz) + 0.746;
696 table3gpp->
m_cDS = 3.91e-9;
707 for (uint8_t row = 0; row < 6; row++)
709 for (uint8_t column = 0; column < 6; column++)
718 if (channelCondition->IsLos ())
724 table3gpp->
m_uLgDS = -0.2 * log10 (1 + fcGHz) - 7.5;
726 table3gpp->
m_uLgASD = -0.1 * log10 (1 + fcGHz) + 1.6;
728 table3gpp->
m_uLgASA = -0.1 * log10 (1 + fcGHz) + 1.6;
730 table3gpp->
m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73,
731 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34,
732 table3gpp->
m_uLgZSD = -0.1 * log10 (1 + fcGHz) + 0.73;
733 table3gpp->
m_sigLgZSD = -0.04 * log10 (1 + fcGHz) + 0.34;
735 table3gpp->
m_cDS = 5;
739 table3gpp->
m_uK = 3.48;
746 for (uint8_t row = 0; row < 7; row++)
748 for (uint8_t column = 0; column < 7; column++)
754 else if (channelCondition->IsNlos ())
758 table3gpp->
m_uLgDS = -0.3 * log10 (1 + fcGHz) - 7;
760 table3gpp->
m_uLgASD = -0.08 * log10 (1 + fcGHz) + 1.81;
761 table3gpp->
m_sigLgASD = 0.05 * log10 (1 + fcGHz) + 0.3;
762 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
763 table3gpp->
m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
764 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92,
765 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
766 table3gpp->
m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
767 table3gpp->
m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
769 table3gpp->
m_cDS = 11;
780 for (uint8_t row = 0; row < 6; row++)
782 for (uint8_t column = 0; column < 6; column++)
788 else if (channelCondition->IsNlosv ())
792 table3gpp->
m_uLgDS = -0.4 * log10 (1 + fcGHz) - 7;
794 table3gpp->
m_uLgASD = -0.1 * log10 (1 + fcGHz) + 1.7;
796 table3gpp->
m_uLgASA = -0.1 * log10 (1 + fcGHz) + 1.7;
798 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
799 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
800 table3gpp->
m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
801 table3gpp->
m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
803 table3gpp->
m_cDS = 11;
814 for (uint8_t row = 0; row < 6; row++)
816 for (uint8_t column = 0; column < 6; column++)
829 if (channelCondition->IsLos ())
839 table3gpp->
m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73;
840 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34;
841 table3gpp->
m_uLgZSD = -0.1 * log10 (1 + fcGHz) + 0.73;
842 table3gpp->
m_sigLgZSD = -0.04 * log10 (1 + fcGHz) + 0.34;
844 table3gpp->
m_cDS = 5;
855 for (uint8_t row = 0; row < 7; row++)
857 for (uint8_t column = 0; column < 7; column++)
863 else if (channelCondition->IsNlosv ())
873 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
874 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
875 table3gpp->
m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
876 table3gpp->
m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
878 table3gpp->
m_cDS = 11;
889 for (uint8_t row = 0; row < 6; row++)
891 for (uint8_t column = 0; column < 6; column++)
897 else if (channelCondition->IsNlos ())
899 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");
903 table3gpp->
m_uLgDS = -0.3 * log10 (1 + fcGHz) - 7;
905 table3gpp->
m_uLgASD = -0.08 * log10 (1 + fcGHz) + 1.81;
906 table3gpp->
m_sigLgASD = 0.05 * log10 (1 + fcGHz) + 0.3;
907 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
908 table3gpp->
m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
909 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92,
910 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
911 table3gpp->
m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
912 table3gpp->
m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
914 table3gpp->
m_cDS = 11;
925 for (uint8_t row = 0; row < 6; row++)
927 for (uint8_t column = 0; column < 6; column++)
981 uint32_t channelId =
GetKey (x1, x2);
989 bool notFound =
false;
1008 if (notFound || update)
1011 Angles txAngle (bMob->GetPosition (), aMob->GetPosition ());
1012 Angles rxAngle (aMob->GetPosition (), bMob->GetPosition ());
1014 double x = aMob->GetPosition ().x - bMob->GetPosition ().x;
1015 double y = aMob->GetPosition ().y - bMob->GetPosition ().y;
1016 double distance2D = sqrt (
x *
x + y * y);
1020 double hUt =
std::min (aMob->GetPosition ().z, bMob->GetPosition ().z);
1021 double hBs =
std::max (aMob->GetPosition ().z, bMob->GetPosition ().z);
1027 Vector locUt = Vector (0.0, 0.0, 0.0);
1029 channelMatrix =
GetNewChannel (locUt, condition, aAntenna, bAntenna, rxAngle, txAngle, distance2D, hBs, hUt);
1030 channelMatrix->
m_nodeIds = std::make_pair (aMob->GetObject<
Node> ()->
GetId (), bMob->GetObject<
Node> ()->GetId ());
1036 return channelMatrix;
1044 double dis2D,
double hBS,
double hUT)
const 1063 double dis3D = std::sqrt (dis2D * dis2D + (hBS - hUT) * (hBS - hUT));
1065 bool los = channelCondition->IsLos ();
1066 bool o2i = channelCondition->IsO2i ();
1080 for (uint8_t iter = 0; iter < paramNum; iter++)
1082 LSPsIndep.push_back (
m_normalRv->GetValue ());
1084 for (uint8_t row = 0; row < paramNum; row++)
1087 for (uint8_t column = 0; column < paramNum; column++)
1089 temp += table3gpp->
m_sqrtC[row][column] * LSPsIndep[column];
1091 LSPs.push_back (temp);
1096 double DS,ASD,ASA,ZSA,ZSD,K_factor = 0;
1099 K_factor = LSPs[1] * table3gpp->
m_sigK + table3gpp->
m_uK;
1120 channelParams->
m_DS = DS;
1121 channelParams->
m_K = K_factor;
1123 NS_LOG_INFO (
"K-factor=" << K_factor <<
",DS=" << DS <<
", ASD=" << ASD <<
", ASA=" << ASA <<
", ZSD=" << ZSD <<
", ZSA=" << ZSA);
1127 double minTau = 100.0;
1128 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1135 clusterDelay.push_back (tau);
1138 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1140 clusterDelay[cIndex] -= minTau;
1142 std::sort (clusterDelay.begin (), clusterDelay.end ());
1149 double powerSum = 0;
1150 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1152 double power = exp (-1 * clusterDelay[cIndex] * (table3gpp->
m_rTau - 1) / table3gpp->
m_rTau / DS) *
1155 clusterPower.push_back (power);
1157 double powerMax = 0;
1159 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1161 clusterPower[cIndex] = clusterPower[cIndex] / powerSum;
1167 double K_linear = pow (10,K_factor / 10);
1169 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1173 clusterPowerForAngles.push_back (clusterPower[cIndex] / (1 + K_linear) + K_linear / (1 + K_linear));
1177 clusterPowerForAngles.push_back (clusterPower[cIndex] / (1 + K_linear));
1179 if (powerMax < clusterPowerForAngles[cIndex])
1181 powerMax = clusterPowerForAngles[cIndex];
1187 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1189 clusterPowerForAngles.push_back (clusterPower[cIndex]);
1190 if (powerMax < clusterPowerForAngles[cIndex])
1192 powerMax = clusterPowerForAngles[cIndex];
1199 double thresh = 0.0032;
1200 for (uint8_t cIndex = numOfCluster; cIndex > 0; cIndex--)
1202 if (clusterPowerForAngles[cIndex - 1] < thresh * powerMax )
1204 clusterPowerForAngles.erase (clusterPowerForAngles.begin () + cIndex - 1);
1205 clusterPower.erase (clusterPower.begin () + cIndex - 1);
1206 clusterDelay.erase (clusterDelay.begin () + cIndex - 1);
1210 NS_ASSERT (clusterPower.size () < UINT8_MAX);
1211 uint8_t numReducedCluster = clusterPower.size ();
1217 double C_tau = 0.7705 - 0.0433 * K_factor + 2e-4 * pow (K_factor,2) + 17e-6 * pow (K_factor,3);
1218 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1220 clusterDelay[cIndex] = clusterDelay[cIndex] / C_tau;
1226 double C_NLOS, C_phi;
1229 switch (numOfCluster)
1270 C_phi = C_NLOS * (1.1035 - 0.028 * K_factor - 2e-3 * pow (K_factor,2) + 1e-4 * pow (K_factor,3));
1278 switch (numOfCluster)
1307 C_theta = C_NLOS * (1.3086 + 0.0339 * K_factor - 0.0077 * pow (K_factor,2) + 2e-4 * pow (K_factor,3));
1315 DoubleVector clusterAoa, clusterAod, clusterZoa, clusterZod;
1317 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1319 angle = 2 * ASA * sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi;
1320 clusterAoa.push_back (angle);
1321 angle = 2 * ASD * sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi;
1322 clusterAod.push_back (angle);
1323 angle = -1 * ZSA * log (clusterPowerForAngles[cIndex] / powerMax) / C_theta;
1324 clusterZoa.push_back (angle);
1325 angle = -1 * ZSD * log (clusterPowerForAngles[cIndex] / powerMax) / C_theta;
1326 clusterZod.push_back (angle);
1329 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1336 clusterAoa[cIndex] = clusterAoa[cIndex] * Xn + (
m_normalRv->GetValue () * ASA / 7) + uAngle.
phi * 180 / M_PI;
1337 clusterAod[cIndex] = clusterAod[cIndex] * Xn + (
m_normalRv->GetValue () * ASD / 7) + sAngle.
phi * 180 / M_PI;
1340 clusterZoa[cIndex] = clusterZoa[cIndex] * Xn + (
m_normalRv->GetValue () * ZSA / 7) + 90;
1344 clusterZoa[cIndex] = clusterZoa[cIndex] * Xn + (
m_normalRv->GetValue () * ZSA / 7) + uAngle.
theta * 180 / M_PI;
1346 clusterZod[cIndex] = clusterZod[cIndex] * Xn + (
m_normalRv->GetValue () * ZSD / 7) + sAngle.
theta * 180 / M_PI + table3gpp->
m_offsetZOD;
1354 double diffAoa = clusterAoa[0] - uAngle.
phi * 180 / M_PI;
1355 double diffAod = clusterAod[0] - sAngle.
phi * 180 / M_PI;
1356 double diffZsa = clusterZoa[0] - uAngle.
theta * 180 / M_PI;
1357 double diffZsd = clusterZod[0] - sAngle.
theta * 180 / M_PI;
1359 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1361 clusterAoa[cIndex] -= diffAoa;
1362 clusterAod[cIndex] -= diffAod;
1363 clusterZoa[cIndex] -= diffZsa;
1364 clusterZod[cIndex] -= diffZsd;
1369 double rayAoa_radian[numReducedCluster][raysPerCluster];
1370 double rayAod_radian[numReducedCluster][raysPerCluster];
1371 double rayZoa_radian[numReducedCluster][raysPerCluster];
1372 double rayZod_radian[numReducedCluster][raysPerCluster];
1374 for (uint8_t nInd = 0; nInd < numReducedCluster; nInd++)
1376 for (uint8_t mInd = 0; mInd < raysPerCluster; mInd++)
1379 while (tempAoa > 360)
1389 NS_ASSERT_MSG (tempAoa >= 0 && tempAoa <= 360,
"the AOA should be the range of [0,360]");
1390 rayAoa_radian[nInd][mInd] = tempAoa * M_PI / 180;
1393 while (tempAod > 360)
1402 NS_ASSERT_MSG (tempAod >= 0 && tempAod <= 360,
"the AOD should be the range of [0,360]");
1403 rayAod_radian[nInd][mInd] = tempAod * M_PI / 180;
1407 while (tempZoa > 360)
1419 tempZoa = 360 - tempZoa;
1422 NS_ASSERT_MSG (tempZoa >= 0&&tempZoa <= 180,
"the ZOA should be the range of [0,180]");
1423 rayZoa_radian[nInd][mInd] = tempZoa * M_PI / 180;
1425 double tempZod = clusterZod[nInd] + 0.375 * pow (10,table3gpp->
m_uLgZSD) *
offSetAlpha[mInd];
1427 while (tempZod > 360)
1438 tempZod = 360 - tempZod;
1440 NS_ASSERT_MSG (tempZod >= 0&&tempZod <= 180,
"the ZOD should be the range of [0,180]");
1441 rayZod_radian[nInd][mInd] = tempZod * M_PI / 180;
1445 double sizeTemp = clusterZoa.size ();
1446 for (uint8_t ind = 0; ind < 4; ind++)
1451 angle_degree = clusterAoa;
1454 angle_degree = clusterZoa;
1457 angle_degree = clusterAod;
1460 angle_degree = clusterZod;
1466 for (uint8_t nIndex = 0; nIndex < sizeTemp; nIndex++)
1468 while (angle_degree[nIndex] > 360)
1470 angle_degree[nIndex] -= 360;
1473 while (angle_degree[nIndex] < 0)
1475 angle_degree[nIndex] += 360;
1478 if (ind == 1 || ind == 3)
1480 if (angle_degree[nIndex] > 180)
1482 angle_degree[nIndex] = 360 - angle_degree[nIndex];
1489 clusterAoa = angle_degree;
1492 clusterZoa = angle_degree;
1495 clusterAod = angle_degree;
1498 clusterZod = angle_degree;
1509 for (uint8_t cInd = 0; cInd < numReducedCluster; cInd++)
1511 clusterPower[cInd] = clusterPower[cInd] / pow (10,attenuation_dB[cInd] / 10);
1516 attenuation_dB.push_back (0);
1521 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1523 Shuffle (&rayAod_radian[cIndex][0], &rayAod_radian[cIndex][raysPerCluster]);
1524 Shuffle (&rayAoa_radian[cIndex][0], &rayAoa_radian[cIndex][raysPerCluster]);
1525 Shuffle (&rayZod_radian[cIndex][0], &rayZod_radian[cIndex][raysPerCluster]);
1526 Shuffle (&rayZoa_radian[cIndex][0], &rayZoa_radian[cIndex][raysPerCluster]);
1533 for (uint8_t nInd = 0; nInd < numReducedCluster; nInd++)
1537 for (uint8_t mInd = 0; mInd < raysPerCluster; mInd++)
1539 double uXprLinear = pow (10, table3gpp->
m_uXpr / 10);
1540 double sigXprLinear = pow (10, table3gpp->
m_sigXpr / 10);
1542 temp.push_back (std::pow (10, (
m_normalRv->GetValue () * sigXprLinear + uXprLinear) / 10));
1544 for (uint8_t pInd = 0; pInd < 4; pInd++)
1548 temp2.push_back (temp3);
1550 crossPolarizationPowerRatios.push_back (temp);
1551 clusterPhase.push_back (temp2);
1560 uint64_t uSize = uAntenna->GetNumberOfElements ();
1561 uint64_t sSize = sAntenna->GetNumberOfElements ();
1563 uint8_t cluster1st = 0, cluster2nd = 0;
1564 double maxPower = 0;
1565 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1567 if (maxPower < clusterPower[cIndex])
1569 maxPower = clusterPower[cIndex];
1570 cluster1st = cIndex;
1574 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1576 if (maxPower < clusterPower[cIndex] && cluster1st != cIndex)
1578 maxPower = clusterPower[cIndex];
1579 cluster2nd = cIndex;
1583 NS_LOG_INFO (
"1st strongest cluster:" << (
int)cluster1st <<
", 2nd strongest cluster:" << (
int)cluster2nd);
1589 H_usn.resize (uSize);
1590 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1592 H_usn[uIndex].resize (sSize);
1593 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1595 H_usn[uIndex][sIndex].resize (numReducedCluster);
1600 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1602 Vector uLoc = uAntenna->GetElementLocation (uIndex);
1604 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1607 Vector sLoc = sAntenna->GetElementLocation (sIndex);
1609 for (uint8_t nIndex = 0; nIndex < numReducedCluster; nIndex++)
1612 if (nIndex != cluster1st && nIndex != cluster2nd)
1614 std::complex<double> rays (0,0);
1615 for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++)
1617 DoubleVector initialPhase = clusterPhase[nIndex][mIndex];
1618 double k = crossPolarizationPowerRatios[nIndex][mIndex];
1620 double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x
1621 + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y
1622 + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z);
1624 double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x
1625 + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y
1626 + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z);
1629 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1630 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (rayAoa_radian[nIndex][mIndex], rayZoa_radian[nIndex][mIndex]));
1631 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (rayAod_radian[nIndex][mIndex], rayZod_radian[nIndex][mIndex]));
1633 rays += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1634 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1635 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1636 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1637 * exp (std::complex<double> (0, rxPhaseDiff))
1638 * exp (std::complex<double> (0, txPhaseDiff));
1640 rays *= sqrt (clusterPower[nIndex] / raysPerCluster);
1641 H_usn[uIndex][sIndex][nIndex] = rays;
1645 std::complex<double> raysSub1 (0,0);
1646 std::complex<double> raysSub2 (0,0);
1647 std::complex<double> raysSub3 (0,0);
1649 for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++)
1651 double k = crossPolarizationPowerRatios[nIndex][mIndex];
1655 DoubleVector initialPhase = clusterPhase[nIndex][mIndex];
1656 double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x
1657 + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y
1658 + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z);
1659 double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x
1660 + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y
1661 + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z);
1663 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1664 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (rayAoa_radian[nIndex][mIndex], rayZoa_radian[nIndex][mIndex]));
1665 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (rayAod_radian[nIndex][mIndex], rayZod_radian[nIndex][mIndex]));
1675 raysSub2 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1676 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1677 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1678 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1679 * exp (std::complex<double> (0, rxPhaseDiff))
1680 * exp (std::complex<double> (0, txPhaseDiff));
1686 raysSub3 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1687 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1688 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1689 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1690 * exp (std::complex<double> (0, rxPhaseDiff))
1691 * exp (std::complex<double> (0, txPhaseDiff));
1694 raysSub1 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1695 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1696 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1697 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1698 * exp (std::complex<double> (0, rxPhaseDiff))
1699 * exp (std::complex<double> (0, txPhaseDiff));
1703 raysSub1 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1704 raysSub2 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1705 raysSub3 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1706 H_usn[uIndex][sIndex][nIndex] = raysSub1;
1707 H_usn[uIndex][sIndex].push_back (raysSub2);
1708 H_usn[uIndex][sIndex].push_back (raysSub3);
1714 std::complex<double> ray (0,0);
1715 double rxPhaseDiff = 2 * M_PI * (sin (uAngle.
theta) * cos (uAngle.
phi) * uLoc.x
1716 + sin (uAngle.
theta) * sin (uAngle.
phi) * uLoc.y
1717 + cos (uAngle.
theta) * uLoc.z);
1718 double txPhaseDiff = 2 * M_PI * (sin (sAngle.
theta) * cos (sAngle.
phi) * sLoc.x
1719 + sin (sAngle.
theta) * sin (sAngle.
phi) * sLoc.y
1720 + cos (sAngle.
theta) * sLoc.z);
1722 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1723 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (uAngle.
phi, uAngle.
theta));
1724 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (sAngle.
phi, sAngle.
theta));
1728 ray = (rxFieldPatternTheta * txFieldPatternTheta - rxFieldPatternPhi * txFieldPatternPhi)
1729 * exp (std::complex<double> (0, -2 * M_PI * dis3D / lambda))
1730 * exp (std::complex<double> (0, rxPhaseDiff))
1731 * exp (std::complex<double> (0, txPhaseDiff));
1733 double K_linear = pow (10,K_factor / 10);
1735 H_usn[uIndex][sIndex][0] = sqrt (1 / (K_linear + 1)) * H_usn[uIndex][sIndex][0] + sqrt (K_linear / (1 + K_linear)) * ray / pow (10,attenuation_dB[0] / 10);
1736 double tempSize = H_usn[uIndex][sIndex].size ();
1737 for (uint8_t nIndex = 1; nIndex < tempSize; nIndex++)
1739 H_usn[uIndex][sIndex][nIndex] *= sqrt (1 / (K_linear + 1));
1747 if (cluster1st == cluster2nd)
1749 clusterDelay.push_back (clusterDelay[cluster1st] + 1.28 * table3gpp->
m_cDS);
1750 clusterDelay.push_back (clusterDelay[cluster1st] + 2.56 * table3gpp->
m_cDS);
1752 clusterAoa.push_back (clusterAoa[cluster1st]);
1753 clusterAoa.push_back (clusterAoa[cluster1st]);
1755 clusterZoa.push_back (clusterZoa[cluster1st]);
1756 clusterZoa.push_back (clusterZoa[cluster1st]);
1758 clusterAod.push_back (clusterAod[cluster1st]);
1759 clusterAod.push_back (clusterAod[cluster1st]);
1761 clusterZod.push_back (clusterZod[cluster1st]);
1762 clusterZod.push_back (clusterZod[cluster1st]);
1767 if (cluster1st < cluster2nd)
1777 clusterDelay.push_back (clusterDelay[
min] + 1.28 * table3gpp->
m_cDS);
1778 clusterDelay.push_back (clusterDelay[
min] + 2.56 * table3gpp->
m_cDS);
1779 clusterDelay.push_back (clusterDelay[
max] + 1.28 * table3gpp->
m_cDS);
1780 clusterDelay.push_back (clusterDelay[
max] + 2.56 * table3gpp->
m_cDS);
1782 clusterAoa.push_back (clusterAoa[
min]);
1783 clusterAoa.push_back (clusterAoa[
min]);
1784 clusterAoa.push_back (clusterAoa[
max]);
1785 clusterAoa.push_back (clusterAoa[
max]);
1787 clusterZoa.push_back (clusterZoa[
min]);
1788 clusterZoa.push_back (clusterZoa[
min]);
1789 clusterZoa.push_back (clusterZoa[
max]);
1790 clusterZoa.push_back (clusterZoa[
max]);
1792 clusterAod.push_back (clusterAod[
min]);
1793 clusterAod.push_back (clusterAod[
min]);
1794 clusterAod.push_back (clusterAod[
max]);
1795 clusterAod.push_back (clusterAod[
max]);
1797 clusterZod.push_back (clusterZod[
min]);
1798 clusterZod.push_back (clusterZod[
min]);
1799 clusterZod.push_back (clusterZod[
max]);
1800 clusterZod.push_back (clusterZod[
max]);
1805 NS_LOG_INFO (
"size of coefficient matrix =[" << H_usn.size () <<
"][" << H_usn[0].size () <<
"][" << H_usn[0][0].size () <<
"]");
1808 channelParams->
m_delay = clusterDelay;
1810 channelParams->
m_angle.clear ();
1811 channelParams->
m_angle.push_back (clusterAoa);
1812 channelParams->
m_angle.push_back (clusterZoa);
1813 channelParams->
m_angle.push_back (clusterAod);
1814 channelParams->
m_angle.push_back (clusterZod);
1816 return channelParams;
1827 uint8_t clusterNum = clusterAOA.size ();
1828 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
1830 powerAttenuation.push_back (0);
1836 double phi_sb, x_sb, theta_sb, y_sb;
1854 if (params->m_nonSelfBlocking.size () == 0)
1864 table.push_back (90);
1866 table.push_back (2);
1871 table.push_back (90);
1872 table.push_back (5);
1873 table.push_back (10);
1875 params->m_nonSelfBlocking.push_back (table);
1880 double deltaX = sqrt (pow (params->m_preLocUT.x - params->m_locUT.x, 2) + pow (params->m_preLocUT.y - params->m_locUT.y, 2));
1893 if (params->m_channelCondition->IsO2i ())
1906 R = exp (-1 * (deltaX / corrDis + (
Now ().GetSeconds () - params->m_generatedTime.GetSeconds ()) / corrT));
1910 R = exp (-1 * (deltaX / corrDis));
1914 <<
" Time difference:" <<
Now ().GetSeconds () - params->m_generatedTime.GetSeconds ()
1915 <<
" correlation:" << R);
1924 if (R * R * (-0.069) + R * 1.074 - 0.002 < 1)
1926 R = R * R * (-0.069) + R * 1.074 - 0.002;
1932 params->m_nonSelfBlocking[blockInd][
PHI_INDEX] =
1933 R * params->m_nonSelfBlocking[blockInd][
PHI_INDEX] + sqrt (1 - R * R) *
m_normalRv->GetValue ();
1940 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
1942 NS_ASSERT_MSG (clusterAOA[cInd] >= 0 && clusterAOA[cInd] <= 360,
"the AOA should be the range of [0,360]");
1943 NS_ASSERT_MSG (clusterZOA[cInd] >= 0 && clusterZOA[cInd] <= 180,
"the ZOA should be the range of [0,180]");
1946 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phi_sb - x_sb / 2 <<
"," << phi_sb + x_sb / 2 <<
"]");
1947 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << theta_sb - y_sb / 2 <<
"," << theta_sb + y_sb / 2 <<
"]");
1948 if ( std::abs (clusterAOA[cInd] - phi_sb) < (x_sb / 2) && std::abs (clusterZOA[cInd] - theta_sb) < (y_sb / 2))
1950 powerAttenuation[cInd] += 30;
1951 NS_LOG_INFO (
"Cluster[" << (
int)cInd <<
"] is blocked by self blocking region and reduce 30 dB power," 1952 "the attenuation is [" << powerAttenuation[cInd] <<
" dB]");
1956 double phiK, xK, thetaK, yK;
1960 phiK = (0.5 * erfc (-1 * params->m_nonSelfBlocking[blockInd][
PHI_INDEX] / sqrt (2))) * 360;
1971 xK = params->m_nonSelfBlocking[blockInd][
X_INDEX];
1972 thetaK = params->m_nonSelfBlocking[blockInd][
THETA_INDEX];
1973 yK = params->m_nonSelfBlocking[blockInd][
Y_INDEX];
1974 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phiK - xK <<
"," << phiK + xK <<
"]");
1975 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << thetaK - yK <<
"," << thetaK + yK <<
"]");
1977 if ( std::abs (clusterAOA[cInd] - phiK) < (xK)
1978 && std::abs (clusterZOA[cInd] - thetaK) < (yK))
1980 double A1 = clusterAOA[cInd] - (phiK + xK / 2);
1981 double A2 = clusterAOA[cInd] - (phiK - xK / 2);
1982 double Z1 = clusterZOA[cInd] - (thetaK + yK / 2);
1983 double Z2 = clusterZOA[cInd] - (thetaK - yK / 2);
1984 int signA1, signA2, signZ1, signZ2;
1986 if (xK / 2 < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= xK)
1994 if (-1 * xK < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= -1 * xK / 2)
2003 if (yK / 2 < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= yK)
2011 if (-1 * yK < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= -1 * yK / 2)
2020 double F_A1 = atan (signA1 * M_PI / 2 * sqrt (M_PI / lambda *
2021 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (A1 * M_PI / 180) - 1))) / M_PI;
2022 double F_A2 = atan (signA2 * M_PI / 2 * sqrt (M_PI / lambda *
2023 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (A2 * M_PI / 180) - 1))) / M_PI;
2024 double F_Z1 = atan (signZ1 * M_PI / 2 * sqrt (M_PI / lambda *
2025 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (Z1 * M_PI / 180) - 1))) / M_PI;
2026 double F_Z2 = atan (signZ2 * M_PI / 2 * sqrt (M_PI / lambda *
2027 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (Z2 * M_PI / 180) - 1))) / M_PI;
2028 double L_dB = -20 * log10 (1 - (F_A1 + F_A2) * (F_Z1 + F_Z2));
2029 powerAttenuation[cInd] += L_dB;
2030 NS_LOG_INFO (
"Cluster[" << (
int)cInd <<
"] is blocked by no-self blocking, " 2031 "the loss is [" << L_dB <<
"]" <<
" dB");
2036 return powerAttenuation;
2043 for (
auto i = (last -
first) - 1; i > 0; --i)
static const double offSetAlpha[20]
static const double sqrtC_UMa_LOS[7][7]
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
This is an interface for a channel model that can be described by a channel matrix, e.g., the 3GPP Spatial Channel Models, which is generally used in combination with antenna arrays.
std::unordered_map< uint32_t, Ptr< ThreeGppChannelMatrix > > m_channelMap
map containing the channel realizations
Smart pointer class similar to boost::intrusive_ptr.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
AttributeValue implementation for Boolean.
static const double sqrtC_office_NLOS[6][6]
uint32_t GetId(void) const
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
~ThreeGppChannelModel()
Destructor.
Hold variables of type string.
static const double sqrtC_UMi_O2I[6][6]
void DoDispose() override
Destructor implementation.
static const uint8_t THETA_INDEX
index of the THETA value in the m_nonSelfBlocking array
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Ptr< NormalRandomVariable > m_normalRv
normal random variable
std::string GetScenario(void) const
Returns the propagation scenario.
Ptr< UniformRandomVariable > m_uniformRvShuffle
uniform random variable used to shuffle array in GetNewChannel
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Hold a signed integer type.
std::vector< Complex2DVector > Complex3DVector
type definition for complex 3D matrices
Time m_generatedTime
generation time
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
double theta
the inclination angle in radians
std::vector< double > DoubleVector
type definition for vectors of doubles
static const uint8_t R_INDEX
index of the R value in the m_nonSelfBlocking array
DoubleVector m_delay
cluster delay in nanoseconds.
void SetChannelConditionModel(Ptr< ChannelConditionModel > model)
Set the channel condition model.
Ptr< ChannelConditionModel > m_channelConditionModel
the channel condition model
std::string m_scenario
the 3GPP scenario
static const double sqrtC_UMa_O2I[6][6]
std::pair< uint32_t, uint32_t > m_nodeIds
the first element is the s-node ID (the transmitter when the channel was generated), the second element is the u-node ID (the receiver when the channel was generated)
static const uint8_t X_INDEX
index of the X value in the m_nonSelfBlocking array
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 AttributeChecker > MakeStringChecker(void)
static const double sqrtC_office_LOS[7][7]
void SetFrequency(double f)
Sets the center frequency of the model.
double GetFrequency(void) const
Returns the center frequency.
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
bool IsZero(void) const
Exactly equivalent to t == 0.
AttributeValue implementation for Time.
ThreeGppChannelModel()
Constructor.
uint16_t m_numNonSelfBlocking
number of non-self-blocking regions
static const double sqrtC_RMa_LOS[7][7]
Time m_updatePeriod
the channel update period
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
Ptr< const ChannelMatrix > GetChannel(Ptr< const MobilityModel > aMob, Ptr< const MobilityModel > bMob, Ptr< const ThreeGppAntennaArrayModel > aAntenna, Ptr< const ThreeGppAntennaArrayModel > bAntenna) override
Looks for the channel matrix associated to the aMob and bMob pair in m_channelMap.
bool m_portraitMode
true if potrait mode, false if landscape
Ptr< const ChannelCondition > m_channelCondition
the channel condition
Complex3DVector m_channel
channel matrix H[u][s][n].
MatrixBasedChannelModel::Double3DVector m_clusterPhase
the initial random phases
double m_blockerSpeed
the blocker speed
double f(double x, void *params)
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.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Hold objects of type Ptr<T>.
Ptr< UniformRandomVariable > m_uniformRv
uniform random variable
static constexpr uint32_t GetKey(uint32_t x1, uint32_t x2)
Calculate the channel key using the Cantor function.
std::vector< DoubleVector > Double2DVector
type definition for matrices of doubles
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
static Time Now(void)
Return the current simulation virtual time.
static const double sqrtC_RMa_NLOS[6][6]
uint8_t m_numCluster
reduced cluster number;
Double2DVector m_angle
cluster angle angle[direction][n], where direction = 0(AOA), 1(ZOA), 2(AOD), 3(ZOD) in degree...
static const double sqrtC_RMa_O2I[6][6]
std::vector< Double2DVector > Double3DVector
type definition for 3D matrices of doubles
#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 AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
double max(double x, double y)
void SetScenario(const std::string &scenario)
Sets the propagation scenario.
double m_perClusterShadowingStd
static const uint8_t PHI_INDEX
index of the PHI value in the m_nonSelfBlocking array
bool m_blockage
enables the blockage model A
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Ptr< ThreeGppChannelMatrix > GetNewChannel(Vector locUT, Ptr< const ChannelCondition > channelCondition, Ptr< const ThreeGppAntennaArrayModel > sAntenna, Ptr< const ThreeGppAntennaArrayModel > uAntenna, Angles &uAngle, Angles &sAngle, double dis2D, double hBS, double hUT) const
Compute the channel matrix between two devices using the procedure described in 3GPP TR 38...
static TypeId GetTypeId()
Get the type ID.
bool ChannelMatrixNeedsUpdate(Ptr< const ThreeGppChannelMatrix > channelMatrix, Ptr< const ChannelCondition > channelCondition) const
Check if the channel matrix has to be updated.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Ptr< const AttributeChecker > MakeBooleanChecker(void)
double phi
the azimuth angle in radians
void Shuffle(double *first, double *last) const
Shuffle the elements of a simple sequence container of type double.
double min(double x, double y)
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
struct holding the azimuth and inclination angles of spherical coordinates.
A base class which provides memory management and object aggregation.
Ptr< const AttributeAccessor > MakeStringAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
static const double sqrtC_UMa_NLOS[6][6]
This class can be used to hold variables of floating point type such as 'double' or 'float'...
Ptr< ChannelConditionModel > GetChannelConditionModel() const
Get the associated channel condition model.
static const uint8_t Y_INDEX
index of the Y value in the m_nonSelfBlocking array
a unique identifier for an interface.
static const double sqrtC_UMi_LOS[7][7]
DoubleVector CalcAttenuationOfBlockage(Ptr< ThreeGppChannelMatrix > params, const DoubleVector &clusterAOA, const DoubleVector &clusterZOA) const
Applies the blockage model A described in 3GPP TR 38.901.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
static const double sqrtC_UMi_NLOS[6][6]
double m_frequency
the operating frequency