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,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++)
1340 clusterZoa[cIndex] = clusterZoa[cIndex] * Xn + (
m_normalRv->GetValue () * ZSA / 7) + 90;
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++)
1383 double tempZod = clusterZod[nInd] + 0.375 * pow (10,table3gpp->
m_uLgZSD) *
offSetAlpha[mInd];
1388 double sizeTemp = clusterZoa.size ();
1389 for (uint8_t ind = 0; ind < 4; ind++)
1394 angle_degree = clusterAoa;
1397 angle_degree = clusterZoa;
1400 angle_degree = clusterAod;
1403 angle_degree = clusterZod;
1409 for (uint8_t nIndex = 0; nIndex < sizeTemp; nIndex++)
1411 while (angle_degree[nIndex] > 360)
1413 angle_degree[nIndex] -= 360;
1416 while (angle_degree[nIndex] < 0)
1418 angle_degree[nIndex] += 360;
1421 if (ind == 1 || ind == 3)
1423 if (angle_degree[nIndex] > 180)
1425 angle_degree[nIndex] = 360 - angle_degree[nIndex];
1432 clusterAoa = angle_degree;
1435 clusterZoa = angle_degree;
1438 clusterAod = angle_degree;
1441 clusterZod = angle_degree;
1452 for (uint8_t cInd = 0; cInd < numReducedCluster; cInd++)
1454 clusterPower[cInd] = clusterPower[cInd] / pow (10,attenuation_dB[cInd] / 10);
1459 attenuation_dB.push_back (0);
1464 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1466 Shuffle (&rayAod_radian[cIndex][0], &rayAod_radian[cIndex][raysPerCluster]);
1467 Shuffle (&rayAoa_radian[cIndex][0], &rayAoa_radian[cIndex][raysPerCluster]);
1468 Shuffle (&rayZod_radian[cIndex][0], &rayZod_radian[cIndex][raysPerCluster]);
1469 Shuffle (&rayZoa_radian[cIndex][0], &rayZoa_radian[cIndex][raysPerCluster]);
1476 for (uint8_t nInd = 0; nInd < numReducedCluster; nInd++)
1480 for (uint8_t mInd = 0; mInd < raysPerCluster; mInd++)
1482 double uXprLinear = pow (10, table3gpp->
m_uXpr / 10);
1483 double sigXprLinear = pow (10, table3gpp->
m_sigXpr / 10);
1485 temp.push_back (std::pow (10, (
m_normalRv->GetValue () * sigXprLinear + uXprLinear) / 10));
1487 for (uint8_t pInd = 0; pInd < 4; pInd++)
1491 temp2.push_back (temp3);
1493 crossPolarizationPowerRatios.push_back (temp);
1494 clusterPhase.push_back (temp2);
1503 uint64_t uSize = uAntenna->GetNumberOfElements ();
1504 uint64_t sSize = sAntenna->GetNumberOfElements ();
1506 uint8_t cluster1st = 0, cluster2nd = 0;
1507 double maxPower = 0;
1508 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1510 if (maxPower < clusterPower[cIndex])
1512 maxPower = clusterPower[cIndex];
1513 cluster1st = cIndex;
1517 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1519 if (maxPower < clusterPower[cIndex] && cluster1st != cIndex)
1521 maxPower = clusterPower[cIndex];
1522 cluster2nd = cIndex;
1526 NS_LOG_INFO (
"1st strongest cluster:" << (
int)cluster1st <<
", 2nd strongest cluster:" << (
int)cluster2nd);
1532 H_usn.resize (uSize);
1533 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1535 H_usn[uIndex].resize (sSize);
1536 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1538 H_usn[uIndex][sIndex].resize (numReducedCluster);
1543 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1545 Vector uLoc = uAntenna->GetElementLocation (uIndex);
1547 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1550 Vector sLoc = sAntenna->GetElementLocation (sIndex);
1552 for (uint8_t nIndex = 0; nIndex < numReducedCluster; nIndex++)
1555 if (nIndex != cluster1st && nIndex != cluster2nd)
1557 std::complex<double> rays (0,0);
1558 for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++)
1560 DoubleVector initialPhase = clusterPhase[nIndex][mIndex];
1561 double k = crossPolarizationPowerRatios[nIndex][mIndex];
1563 double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x
1564 + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y
1565 + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z);
1567 double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x
1568 + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y
1569 + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z);
1572 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1573 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (rayAoa_radian[nIndex][mIndex], rayZoa_radian[nIndex][mIndex]));
1574 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (rayAod_radian[nIndex][mIndex], rayZod_radian[nIndex][mIndex]));
1576 rays += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1577 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 /
k) * rxFieldPatternTheta * txFieldPatternPhi +
1578 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 /
k) * rxFieldPatternPhi * txFieldPatternTheta +
1579 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1580 * exp (std::complex<double> (0, rxPhaseDiff))
1581 * exp (std::complex<double> (0, txPhaseDiff));
1583 rays *= sqrt (clusterPower[nIndex] / raysPerCluster);
1584 H_usn[uIndex][sIndex][nIndex] = rays;
1588 std::complex<double> raysSub1 (0,0);
1589 std::complex<double> raysSub2 (0,0);
1590 std::complex<double> raysSub3 (0,0);
1592 for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++)
1594 double k = crossPolarizationPowerRatios[nIndex][mIndex];
1598 DoubleVector initialPhase = clusterPhase[nIndex][mIndex];
1599 double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x
1600 + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y
1601 + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z);
1602 double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x
1603 + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y
1604 + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z);
1606 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1607 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (rayAoa_radian[nIndex][mIndex], rayZoa_radian[nIndex][mIndex]));
1608 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (rayAod_radian[nIndex][mIndex], rayZod_radian[nIndex][mIndex]));
1618 raysSub2 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1619 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 /
k) * rxFieldPatternTheta * txFieldPatternPhi +
1620 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 /
k) * rxFieldPatternPhi * txFieldPatternTheta +
1621 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1622 * exp (std::complex<double> (0, rxPhaseDiff))
1623 * exp (std::complex<double> (0, txPhaseDiff));
1629 raysSub3 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1630 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 /
k) * rxFieldPatternTheta * txFieldPatternPhi +
1631 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 /
k) * rxFieldPatternPhi * txFieldPatternTheta +
1632 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1633 * exp (std::complex<double> (0, rxPhaseDiff))
1634 * exp (std::complex<double> (0, txPhaseDiff));
1637 raysSub1 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1638 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 /
k) * rxFieldPatternTheta * txFieldPatternPhi +
1639 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 /
k) * rxFieldPatternPhi * txFieldPatternTheta +
1640 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1641 * exp (std::complex<double> (0, rxPhaseDiff))
1642 * exp (std::complex<double> (0, txPhaseDiff));
1646 raysSub1 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1647 raysSub2 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1648 raysSub3 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1649 H_usn[uIndex][sIndex][nIndex] = raysSub1;
1650 H_usn[uIndex][sIndex].push_back (raysSub2);
1651 H_usn[uIndex][sIndex].push_back (raysSub3);
1657 std::complex<double> ray (0,0);
1665 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1671 ray = (rxFieldPatternTheta * txFieldPatternTheta - rxFieldPatternPhi * txFieldPatternPhi)
1672 * exp (std::complex<double> (0, -2 * M_PI * dis3D / lambda))
1673 * exp (std::complex<double> (0, rxPhaseDiff))
1674 * exp (std::complex<double> (0, txPhaseDiff));
1676 double K_linear = pow (10,K_factor / 10);
1678 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);
1679 double tempSize = H_usn[uIndex][sIndex].size ();
1680 for (uint8_t nIndex = 1; nIndex < tempSize; nIndex++)
1682 H_usn[uIndex][sIndex][nIndex] *= sqrt (1 / (K_linear + 1));
1690 if (cluster1st == cluster2nd)
1692 clusterDelay.push_back (clusterDelay[cluster1st] + 1.28 * table3gpp->
m_cDS);
1693 clusterDelay.push_back (clusterDelay[cluster1st] + 2.56 * table3gpp->
m_cDS);
1695 clusterAoa.push_back (clusterAoa[cluster1st]);
1696 clusterAoa.push_back (clusterAoa[cluster1st]);
1698 clusterZoa.push_back (clusterZoa[cluster1st]);
1699 clusterZoa.push_back (clusterZoa[cluster1st]);
1701 clusterAod.push_back (clusterAod[cluster1st]);
1702 clusterAod.push_back (clusterAod[cluster1st]);
1704 clusterZod.push_back (clusterZod[cluster1st]);
1705 clusterZod.push_back (clusterZod[cluster1st]);
1710 if (cluster1st < cluster2nd)
1720 clusterDelay.push_back (clusterDelay[
min] + 1.28 * table3gpp->
m_cDS);
1721 clusterDelay.push_back (clusterDelay[
min] + 2.56 * table3gpp->
m_cDS);
1722 clusterDelay.push_back (clusterDelay[
max] + 1.28 * table3gpp->
m_cDS);
1723 clusterDelay.push_back (clusterDelay[
max] + 2.56 * table3gpp->
m_cDS);
1725 clusterAoa.push_back (clusterAoa[
min]);
1726 clusterAoa.push_back (clusterAoa[
min]);
1727 clusterAoa.push_back (clusterAoa[
max]);
1728 clusterAoa.push_back (clusterAoa[
max]);
1730 clusterZoa.push_back (clusterZoa[
min]);
1731 clusterZoa.push_back (clusterZoa[
min]);
1732 clusterZoa.push_back (clusterZoa[
max]);
1733 clusterZoa.push_back (clusterZoa[
max]);
1735 clusterAod.push_back (clusterAod[
min]);
1736 clusterAod.push_back (clusterAod[
min]);
1737 clusterAod.push_back (clusterAod[
max]);
1738 clusterAod.push_back (clusterAod[
max]);
1740 clusterZod.push_back (clusterZod[
min]);
1741 clusterZod.push_back (clusterZod[
min]);
1742 clusterZod.push_back (clusterZod[
max]);
1743 clusterZod.push_back (clusterZod[
max]);
1748 NS_LOG_INFO (
"size of coefficient matrix =[" << H_usn.size () <<
"][" << H_usn[0].size () <<
"][" << H_usn[0][0].size () <<
"]");
1751 channelParams->
m_delay = clusterDelay;
1753 channelParams->
m_angle.clear ();
1754 channelParams->
m_angle.push_back (clusterAoa);
1755 channelParams->
m_angle.push_back (clusterZoa);
1756 channelParams->
m_angle.push_back (clusterAod);
1757 channelParams->
m_angle.push_back (clusterZod);
1759 return channelParams;
1762 std::pair<double, double>
1765 inclinationRad =
WrapTo2Pi (inclinationRad);
1766 if (inclinationRad > M_PI)
1769 inclinationRad -= M_PI;
1775 NS_ASSERT_MSG (0 <= inclinationRad && inclinationRad <= M_PI,
1776 "inclinationRad=" << inclinationRad <<
" not valid, should be in [0, pi]");
1778 "azimuthRad=" << azimuthRad <<
" not valid, should be in [0, 2*pi]");
1780 return std::make_pair (azimuthRad, inclinationRad);
1791 uint8_t clusterNum = clusterAOA.size ();
1792 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
1794 powerAttenuation.push_back (0);
1800 double phi_sb, x_sb, theta_sb, y_sb;
1818 if (params->m_nonSelfBlocking.size () == 0)
1828 table.push_back (90);
1830 table.push_back (2);
1835 table.push_back (90);
1836 table.push_back (5);
1837 table.push_back (10);
1839 params->m_nonSelfBlocking.push_back (table);
1844 double deltaX = sqrt (pow (params->m_preLocUT.x - params->m_locUT.x, 2) + pow (params->m_preLocUT.y - params->m_locUT.y, 2));
1857 if (params->m_channelCondition->IsO2i ())
1870 R = exp (-1 * (deltaX / corrDis + (
Now ().GetSeconds () - params->m_generatedTime.GetSeconds ()) / corrT));
1874 R = exp (-1 * (deltaX / corrDis));
1878 <<
" Time difference:" <<
Now ().GetSeconds () - params->m_generatedTime.GetSeconds ()
1879 <<
" correlation:" << R);
1888 if (R * R * (-0.069) + R * 1.074 - 0.002 < 1)
1890 R = R * R * (-0.069) + R * 1.074 - 0.002;
1896 params->m_nonSelfBlocking[blockInd][
PHI_INDEX] =
1897 R * params->m_nonSelfBlocking[blockInd][
PHI_INDEX] + sqrt (1 - R * R) *
m_normalRv->GetValue ();
1904 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
1906 NS_ASSERT_MSG (clusterAOA[cInd] >= 0 && clusterAOA[cInd] <= 360,
"the AOA should be the range of [0,360]");
1907 NS_ASSERT_MSG (clusterZOA[cInd] >= 0 && clusterZOA[cInd] <= 180,
"the ZOA should be the range of [0,180]");
1910 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phi_sb - x_sb / 2 <<
"," << phi_sb + x_sb / 2 <<
"]");
1911 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << theta_sb - y_sb / 2 <<
"," << theta_sb + y_sb / 2 <<
"]");
1912 if ( std::abs (clusterAOA[cInd] - phi_sb) < (x_sb / 2) && std::abs (clusterZOA[cInd] - theta_sb) < (y_sb / 2))
1914 powerAttenuation[cInd] += 30;
1915 NS_LOG_INFO (
"Cluster[" << (
int)cInd <<
"] is blocked by self blocking region and reduce 30 dB power," 1916 "the attenuation is [" << powerAttenuation[cInd] <<
" dB]");
1920 double phiK, xK, thetaK, yK;
1924 phiK = (0.5 * erfc (-1 * params->m_nonSelfBlocking[blockInd][
PHI_INDEX] / sqrt (2))) * 360;
1935 xK = params->m_nonSelfBlocking[blockInd][
X_INDEX];
1936 thetaK = params->m_nonSelfBlocking[blockInd][
THETA_INDEX];
1937 yK = params->m_nonSelfBlocking[blockInd][
Y_INDEX];
1938 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phiK - xK <<
"," << phiK + xK <<
"]");
1939 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << thetaK - yK <<
"," << thetaK + yK <<
"]");
1941 if ( std::abs (clusterAOA[cInd] - phiK) < (xK)
1942 && std::abs (clusterZOA[cInd] - thetaK) < (yK))
1944 double A1 = clusterAOA[cInd] - (phiK + xK / 2);
1945 double A2 = clusterAOA[cInd] - (phiK - xK / 2);
1946 double Z1 = clusterZOA[cInd] - (thetaK + yK / 2);
1947 double Z2 = clusterZOA[cInd] - (thetaK - yK / 2);
1948 int signA1, signA2, signZ1, signZ2;
1950 if (xK / 2 < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= xK)
1958 if (-1 * xK < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= -1 * xK / 2)
1967 if (yK / 2 < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= yK)
1975 if (-1 * yK < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= -1 * yK / 2)
1984 double F_A1 = atan (signA1 * M_PI / 2 * sqrt (M_PI / lambda *
1986 double F_A2 = atan (signA2 * M_PI / 2 * sqrt (M_PI / lambda *
1988 double F_Z1 = atan (signZ1 * M_PI / 2 * sqrt (M_PI / lambda *
1990 double F_Z2 = atan (signZ2 * M_PI / 2 * sqrt (M_PI / lambda *
1992 double L_dB = -20 * log10 (1 - (F_A1 + F_A2) * (F_Z1 + F_Z2));
1993 powerAttenuation[cInd] += L_dB;
1994 NS_LOG_INFO (
"Cluster[" << (
int)cInd <<
"] is blocked by no-self blocking, " 1995 "the loss is [" << L_dB <<
"]" <<
" dB");
2000 return powerAttenuation;
2007 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
double DegreesToRadians(double degrees)
converts degrees to radians
Class holding the azimuth and inclination angles of spherical coordinates.
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.
Ptr< ThreeGppChannelMatrix > GetNewChannel(Vector locUT, Ptr< const ChannelCondition > channelCondition, Ptr< const PhasedArrayModel > sAntenna, Ptr< const PhasedArrayModel > 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...
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]
static std::pair< double, double > WrapAngles(double azimuthRad, double inclinationRad)
Wrap an (azimuth, inclination) angle pair in a valid range.
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
double GetAzimuth(void) const
Getter for azimuth angle.
static const double sqrtC_RMa_LOS[7][7]
Time m_updatePeriod
the channel update period
double WrapTo2Pi(double a)
Wrap angle in [0, 2*M_PI)
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
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...
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_channelMap.
static const double sqrtC_RMa_O2I[6][6]
std::vector< Double2DVector > Double3DVector
type definition for 3D matrices of doubles
double RadiansToDegrees(double radians)
converts radians to degrees
#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.
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 GetInclination(void) const
Getter for inclination angle.
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.
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