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 "Unknown scenario, choose between RMa, UMa, UMi-StreetCanyon, InH-OfficeOpen or InH-OfficeMixed");
319 table3gpp->
m_sigLgZSD =
std::max (-1.0, -0.17 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.22);
321 table3gpp->
m_cDS = 3.91e-9;
332 for (uint8_t row = 0; row < 7; row++)
334 for (uint8_t column = 0; column < 7; column++)
340 else if (!los && !o2i)
352 table3gpp->
m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
354 table3gpp->
m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
355 table3gpp->
m_cDS = 3.91e-9;
366 for (uint8_t row = 0; row < 6; row++)
368 for (uint8_t column = 0; column < 6; column++)
386 table3gpp->
m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
388 table3gpp->
m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
389 table3gpp->
m_cDS = 3.91e-9;
400 for (uint8_t row = 0; row < 6; row++)
402 for (uint8_t column = 0; column < 6; column++)
415 table3gpp->
m_uLgDS = -6.955 - 0.0963 * log10 (fcGHz);
417 table3gpp->
m_uLgASD = 1.06 + 0.1114 * log10 (fcGHz);
423 table3gpp->
m_uLgZSD =
std::max (-0.5, -2.1 * distance2D / 1000 - 0.01 * (hUT - 1.5) + 0.75);
426 table3gpp->
m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;
437 for (uint8_t row = 0; row < 7; row++)
439 for (uint8_t column = 0; column < 7; column++)
447 double uLgZSD =
std::max (-0.5, -2.1 * distance2D / 1000 - 0.01 * (hUT - 1.5) + 0.9);
449 double afc = 0.208 * log10 (fcGHz) - 0.782;
451 double cfc = -0.13 * log10 (fcGHz) + 2.03;
452 double efc = 7.66 * log10 (fcGHz) - 5.96;
454 double offsetZOD = efc - std::pow (10, afc * log10 (
std::max (bfc,distance2D)) + cfc);
460 table3gpp->
m_uLgDS = -6.28 - 0.204 * log10 (fcGHz);
462 table3gpp->
m_uLgASD = 1.5 - 0.1144 * log10 (fcGHz);
464 table3gpp->
m_uLgASA = 2.08 - 0.27 * log10 (fcGHz);
466 table3gpp->
m_uLgZSA = -0.3236 * log10 (fcGHz) + 1.512;
471 table3gpp->
m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;;
482 for (uint8_t row = 0; row < 6; row++)
484 for (uint8_t column = 0; column < 6; column++)
505 table3gpp->
m_cDS = 11e-9;
516 for (uint8_t row = 0; row < 6; row++)
518 for (uint8_t column = 0; column < 6; column++)
535 table3gpp->
m_uLgDS = -0.24 * log10 (1 + fcGHz) - 7.14;
537 table3gpp->
m_uLgASD = -0.05 * log10 (1 + fcGHz) + 1.21;
539 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.73;
540 table3gpp->
m_sigLgASA = 0.014 * log10 (1 + fcGHz) + 0.28;
541 table3gpp->
m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73;
542 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34;
543 table3gpp->
m_uLgZSD =
std::max (-0.21, -14.8 * distance2D / 1000 + 0.01 * std::abs (hUT - hBS) + 0.83);
546 table3gpp->
m_cDS = 5e-9;
557 for (uint8_t row = 0; row < 7; row++)
559 for (uint8_t column = 0; column < 7; column++)
567 double uLgZSD =
std::max (-0.5, -3.1 * distance2D / 1000 + 0.01 *
std::max (hUT - hBS,0.0) + 0.2);
568 double offsetZOD = -1 * std::pow (10, -1.5 * log10 (
std::max (10.0, distance2D)) + 3.3);
573 table3gpp->
m_uLgDS = -0.24 * log10 (1 + fcGHz) - 6.83;
574 table3gpp->
m_sigLgDS = 0.16 * log10 (1 + fcGHz) + 0.28;
575 table3gpp->
m_uLgASD = -0.23 * log10 (1 + fcGHz) + 1.53;
576 table3gpp->
m_sigLgASD = 0.11 * log10 (1 + fcGHz) + 0.33;
577 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
578 table3gpp->
m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
579 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
580 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
584 table3gpp->
m_cDS = 11e-9;
595 for (uint8_t row = 0; row < 6; row++)
597 for (uint8_t column = 0; column < 6; column++)
618 table3gpp->
m_cDS = 11e-9;
629 for (uint8_t row = 0; row < 6; row++)
631 for (uint8_t column = 0; column < 6; column++)
641 NS_ASSERT_MSG (!o2i,
"The indoor scenario does out support outdoor to indoor");
646 table3gpp->
m_uLgDS = -0.01 * log10 (1 + fcGHz) - 7.692;
650 table3gpp->
m_uLgASA = -0.19 * log10 (1 + fcGHz) + 1.781;
651 table3gpp->
m_sigLgASA = 0.12 * log10 (1 + fcGHz) + 0.119;
652 table3gpp->
m_uLgZSA = -0.26 * log10 (1 + fcGHz) + 1.44;
653 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.264;
654 table3gpp->
m_uLgZSD = -1.43 * log10 (1 + fcGHz) + 2.228;
655 table3gpp->
m_sigLgZSD = 0.13 * log10 (1 + fcGHz) + 0.30;
657 table3gpp->
m_cDS = 3.91e-9;
668 for (uint8_t row = 0; row < 7; row++)
670 for (uint8_t column = 0; column < 7; column++)
680 table3gpp->
m_uLgDS = -0.28 * log10 (1 + fcGHz) - 7.173;
681 table3gpp->
m_sigLgDS = 0.1 * log10 (1 + fcGHz) + 0.055;
684 table3gpp->
m_uLgASA = -0.11 * log10 (1 + fcGHz) + 1.863;
685 table3gpp->
m_sigLgASA = 0.12 * log10 (1 + fcGHz) + 0.059;
686 table3gpp->
m_uLgZSA = -0.15 * log10 (1 + fcGHz) + 1.387;
687 table3gpp->
m_sigLgZSA = -0.09 * log10 (1 + fcGHz) + 0.746;
691 table3gpp->
m_cDS = 3.91e-9;
702 for (uint8_t row = 0; row < 6; row++)
704 for (uint8_t column = 0; column < 6; column++)
727 if (channelMatrix->
m_los != los)
729 NS_LOG_DEBUG (
"old los condition " << channelMatrix->
m_los <<
" new los condition " << los);
754 uint32_t channelId =
GetKey (x1, x2);
758 bool los = (condition->GetLosCondition () == ChannelCondition::LosConditionValue::LOS);
764 bool notFound =
false;
783 if (notFound || update)
786 Angles txAngle (bMob->GetPosition (), aMob->GetPosition ());
787 Angles rxAngle (aMob->GetPosition (), bMob->GetPosition ());
789 double x = aMob->GetPosition ().x - bMob->GetPosition ().x;
790 double y = aMob->GetPosition ().y - bMob->GetPosition ().y;
791 double distance2D = sqrt (
x *
x + y * y);
795 double hUt =
std::min (aMob->GetPosition ().z, bMob->GetPosition ().z);
796 double hBs =
std::max (aMob->GetPosition ().z, bMob->GetPosition ().z);
802 Vector locUt = Vector (0.0, 0.0, 0.0);
804 channelMatrix =
GetNewChannel (locUt, los, o2i, aAntenna, bAntenna, rxAngle, txAngle, distance2D, hBs, hUt);
805 channelMatrix->
m_nodeIds = std::make_pair (aMob->GetObject<
Node> ()->
GetId (), bMob->GetObject<
Node> ()->GetId ());
811 return channelMatrix;
819 double dis2D,
double hBS,
double hUT)
const 834 channelParams->
m_los = los;
835 channelParams->
m_o2i = o2i;
839 double dis3D = std::sqrt (dis2D * dis2D + (hBS - hUT) * (hBS - hUT));
853 for (uint8_t iter = 0; iter < paramNum; iter++)
855 LSPsIndep.push_back (
m_normalRv->GetValue ());
857 for (uint8_t row = 0; row < paramNum; row++)
860 for (uint8_t column = 0; column < paramNum; column++)
862 temp += table3gpp->
m_sqrtC[row][column] * LSPsIndep[column];
864 LSPs.push_back (temp);
869 double DS,ASD,ASA,ZSA,ZSD,K_factor = 0;
872 K_factor = LSPs[1] * table3gpp->
m_sigK + table3gpp->
m_uK;
893 channelParams->
m_DS = DS;
894 channelParams->
m_K = K_factor;
896 NS_LOG_INFO (
"K-factor=" << K_factor <<
",DS=" << DS <<
", ASD=" << ASD <<
", ASA=" << ASA <<
", ZSD=" << ZSD <<
", ZSA=" << ZSA);
900 double minTau = 100.0;
901 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
908 clusterDelay.push_back (tau);
911 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
913 clusterDelay[cIndex] -= minTau;
915 std::sort (clusterDelay.begin (), clusterDelay.end ());
923 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
925 double power = exp (-1 * clusterDelay[cIndex] * (table3gpp->
m_rTau - 1) / table3gpp->
m_rTau / DS) *
928 clusterPower.push_back (power);
932 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
934 clusterPower[cIndex] = clusterPower[cIndex] / powerSum;
940 double K_linear = pow (10,K_factor / 10);
942 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
946 clusterPowerForAngles.push_back (clusterPower[cIndex] / (1 + K_linear) + K_linear / (1 + K_linear));
950 clusterPowerForAngles.push_back (clusterPower[cIndex] / (1 + K_linear));
952 if (powerMax < clusterPowerForAngles[cIndex])
954 powerMax = clusterPowerForAngles[cIndex];
960 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
962 clusterPowerForAngles.push_back (clusterPower[cIndex]);
963 if (powerMax < clusterPowerForAngles[cIndex])
965 powerMax = clusterPowerForAngles[cIndex];
972 double thresh = 0.0032;
973 for (uint8_t cIndex = numOfCluster; cIndex > 0; cIndex--)
975 if (clusterPowerForAngles[cIndex - 1] < thresh * powerMax )
977 clusterPowerForAngles.erase (clusterPowerForAngles.begin () + cIndex - 1);
978 clusterPower.erase (clusterPower.begin () + cIndex - 1);
979 clusterDelay.erase (clusterDelay.begin () + cIndex - 1);
983 NS_ASSERT(clusterPower.size () < UINT8_MAX);
984 uint8_t numReducedCluster = clusterPower.size ();
990 double C_tau = 0.7705 - 0.0433 * K_factor + 2e-4 * pow (K_factor,2) + 17e-6 * pow (K_factor,3);
991 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
993 clusterDelay[cIndex] = clusterDelay[cIndex] / C_tau;
999 double C_NLOS, C_phi;
1002 switch (numOfCluster)
1043 C_phi = C_NLOS * (1.1035 - 0.028 * K_factor - 2e-3 * pow (K_factor,2) + 1e-4 * pow (K_factor,3));
1051 switch (numOfCluster)
1080 C_theta = C_NLOS * (1.3086 + 0.0339 * K_factor - 0.0077 * pow (K_factor,2) + 2e-4 * pow (K_factor,3));
1088 DoubleVector clusterAoa, clusterAod, clusterZoa, clusterZod;
1090 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1092 angle = 2*ASA*sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi;
1093 clusterAoa.push_back (angle);
1094 angle = 2*ASD*sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi;
1095 clusterAod.push_back (angle);
1096 angle = -1*ZSA*log (clusterPowerForAngles[cIndex] / powerMax) / C_theta;
1097 clusterZoa.push_back (angle);
1098 angle = -1*ZSD*log (clusterPowerForAngles[cIndex] / powerMax) / C_theta;
1099 clusterZod.push_back (angle);
1102 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1109 clusterAoa[cIndex] = clusterAoa[cIndex] * Xn + (
m_normalRv->GetValue () * ASA / 7) + uAngle.
phi * 180 / M_PI;
1110 clusterAod[cIndex] = clusterAod[cIndex] * Xn + (
m_normalRv->GetValue () * ASD / 7) + sAngle.
phi * 180 / M_PI;
1113 clusterZoa[cIndex] = clusterZoa[cIndex] * Xn + (
m_normalRv->GetValue () * ZSA / 7) + 90;
1117 clusterZoa[cIndex] = clusterZoa[cIndex] * Xn + (
m_normalRv->GetValue () * ZSA / 7) + uAngle.
theta * 180 / M_PI;
1119 clusterZod[cIndex] = clusterZod[cIndex] * Xn + (
m_normalRv->GetValue () * ZSD / 7) + sAngle.
theta * 180 / M_PI + table3gpp->
m_offsetZOD;
1127 double diffAoa = clusterAoa[0] - uAngle.
phi * 180 / M_PI;
1128 double diffAod = clusterAod[0] - sAngle.
phi * 180 / M_PI;
1129 double diffZsa = clusterZoa[0] - uAngle.
theta * 180 / M_PI;
1130 double diffZsd = clusterZod[0] - sAngle.
theta * 180 / M_PI;
1132 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1134 clusterAoa[cIndex] -= diffAoa;
1135 clusterAod[cIndex] -= diffAod;
1136 clusterZoa[cIndex] -= diffZsa;
1137 clusterZod[cIndex] -= diffZsd;
1142 double rayAoa_radian[numReducedCluster][raysPerCluster];
1143 double rayAod_radian[numReducedCluster][raysPerCluster];
1144 double rayZoa_radian[numReducedCluster][raysPerCluster];
1145 double rayZod_radian[numReducedCluster][raysPerCluster];
1147 for (uint8_t nInd = 0; nInd < numReducedCluster; nInd++)
1149 for (uint8_t mInd = 0; mInd < raysPerCluster; mInd++)
1152 while (tempAoa > 360)
1162 NS_ASSERT_MSG (tempAoa >= 0 && tempAoa <= 360,
"the AOA should be the range of [0,360]");
1163 rayAoa_radian[nInd][mInd] = tempAoa * M_PI / 180;
1166 while (tempAod > 360)
1175 NS_ASSERT_MSG (tempAod >= 0 && tempAod <= 360,
"the AOD should be the range of [0,360]");
1176 rayAod_radian[nInd][mInd] = tempAod * M_PI / 180;
1180 while (tempZoa > 360)
1192 tempZoa = 360 - tempZoa;
1195 NS_ASSERT_MSG (tempZoa >= 0&&tempZoa <= 180,
"the ZOA should be the range of [0,180]");
1196 rayZoa_radian[nInd][mInd] = tempZoa * M_PI / 180;
1198 double tempZod = clusterZod[nInd] + 0.375 * pow (10,table3gpp->
m_uLgZSD) *
offSetAlpha[mInd];
1200 while (tempZod > 360)
1211 tempZod = 360 - tempZod;
1213 NS_ASSERT_MSG (tempZod >= 0&&tempZod <= 180,
"the ZOD should be the range of [0,180]");
1214 rayZod_radian[nInd][mInd] = tempZod * M_PI / 180;
1218 double sizeTemp = clusterZoa.size ();
1219 for (uint8_t ind = 0; ind < 4; ind++)
1224 angle_degree = clusterAoa;
1227 angle_degree = clusterZoa;
1230 angle_degree = clusterAod;
1233 angle_degree = clusterZod;
1239 for (uint8_t nIndex = 0; nIndex < sizeTemp; nIndex++)
1241 while (angle_degree[nIndex] > 360)
1243 angle_degree[nIndex] -= 360;
1246 while (angle_degree[nIndex] < 0)
1248 angle_degree[nIndex] += 360;
1251 if (ind == 1 || ind == 3)
1253 if (angle_degree[nIndex] > 180)
1255 angle_degree[nIndex] = 360 - angle_degree[nIndex];
1262 clusterAoa = angle_degree;
1265 clusterZoa = angle_degree;
1268 clusterAod = angle_degree;
1271 clusterZod = angle_degree;
1282 for (uint8_t cInd = 0; cInd < numReducedCluster; cInd++)
1284 clusterPower[cInd] = clusterPower[cInd] / pow (10,attenuation_dB[cInd] / 10);
1289 attenuation_dB.push_back (0);
1294 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1296 Shuffle (&rayAod_radian[cIndex][0], &rayAod_radian[cIndex][raysPerCluster]);
1297 Shuffle (&rayAoa_radian[cIndex][0], &rayAoa_radian[cIndex][raysPerCluster]);
1298 Shuffle (&rayZod_radian[cIndex][0], &rayZod_radian[cIndex][raysPerCluster]);
1299 Shuffle (&rayZoa_radian[cIndex][0], &rayZoa_radian[cIndex][raysPerCluster]);
1306 for (uint8_t nInd = 0; nInd < numReducedCluster; nInd++)
1310 for (uint8_t mInd = 0; mInd < raysPerCluster; mInd++)
1312 double uXprLinear = pow (10, table3gpp->
m_uXpr / 10);
1313 double sigXprLinear = pow (10, table3gpp->
m_sigXpr / 10);
1315 temp.push_back (std::pow (10, (
m_normalRv->GetValue () * sigXprLinear + uXprLinear) / 10));
1317 for (uint8_t pInd = 0; pInd < 4; pInd++)
1321 temp2.push_back (temp3);
1323 crossPolarizationPowerRatios.push_back (temp);
1324 clusterPhase.push_back (temp2);
1333 uint64_t uSize = uAntenna->GetNumberOfElements ();
1334 uint64_t sSize = sAntenna->GetNumberOfElements ();
1336 uint8_t cluster1st = 0, cluster2nd = 0;
1337 double maxPower = 0;
1338 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1340 if (maxPower < clusterPower[cIndex])
1342 maxPower = clusterPower[cIndex];
1343 cluster1st = cIndex;
1347 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1349 if (maxPower < clusterPower[cIndex] && cluster1st != cIndex)
1351 maxPower = clusterPower[cIndex];
1352 cluster2nd = cIndex;
1356 NS_LOG_INFO (
"1st strongest cluster:" << (
int)cluster1st <<
", 2nd strongest cluster:" << (
int)cluster2nd);
1362 H_usn.resize (uSize);
1363 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1365 H_usn[uIndex].resize (sSize);
1366 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1368 H_usn[uIndex][sIndex].resize (numReducedCluster);
1373 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1375 Vector uLoc = uAntenna->GetElementLocation (uIndex);
1377 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1380 Vector sLoc = sAntenna->GetElementLocation (sIndex);
1382 for (uint8_t nIndex = 0; nIndex < numReducedCluster; nIndex++)
1385 if (nIndex != cluster1st && nIndex != cluster2nd)
1387 std::complex<double> rays (0,0);
1388 for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++)
1390 DoubleVector initialPhase = clusterPhase[nIndex][mIndex];
1391 double k = crossPolarizationPowerRatios[nIndex][mIndex];
1393 double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x
1394 + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y
1395 + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z);
1397 double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x
1398 + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y
1399 + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z);
1402 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1403 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (rayAoa_radian[nIndex][mIndex], rayZoa_radian[nIndex][mIndex]));
1404 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (rayAod_radian[nIndex][mIndex], rayZod_radian[nIndex][mIndex]));
1406 rays += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1407 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1408 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1409 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1410 * exp (std::complex<double> (0, rxPhaseDiff))
1411 * exp (std::complex<double> (0, txPhaseDiff));
1413 rays *= sqrt (clusterPower[nIndex] / raysPerCluster);
1414 H_usn[uIndex][sIndex][nIndex] = rays;
1418 std::complex<double> raysSub1 (0,0);
1419 std::complex<double> raysSub2 (0,0);
1420 std::complex<double> raysSub3 (0,0);
1422 for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++)
1424 double k = crossPolarizationPowerRatios[nIndex][mIndex];
1428 DoubleVector initialPhase = clusterPhase[nIndex][mIndex];
1429 double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x
1430 + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y
1431 + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z);
1432 double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x
1433 + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y
1434 + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z);
1436 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1437 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (rayAoa_radian[nIndex][mIndex], rayZoa_radian[nIndex][mIndex]));
1438 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (rayAod_radian[nIndex][mIndex], rayZod_radian[nIndex][mIndex]));
1448 raysSub2 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1449 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1450 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1451 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1452 * exp (std::complex<double> (0, rxPhaseDiff))
1453 * exp (std::complex<double> (0, txPhaseDiff));
1459 raysSub3 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1460 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1461 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1462 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1463 * exp (std::complex<double> (0, rxPhaseDiff))
1464 * exp (std::complex<double> (0, txPhaseDiff));
1467 raysSub1 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1468 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1469 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1470 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1471 * exp (std::complex<double> (0, rxPhaseDiff))
1472 * exp (std::complex<double> (0, txPhaseDiff));
1476 raysSub1 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1477 raysSub2 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1478 raysSub3 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1479 H_usn[uIndex][sIndex][nIndex] = raysSub1;
1480 H_usn[uIndex][sIndex].push_back (raysSub2);
1481 H_usn[uIndex][sIndex].push_back (raysSub3);
1487 std::complex<double> ray (0,0);
1488 double rxPhaseDiff = 2 * M_PI * (sin (uAngle.
theta) * cos (uAngle.
phi) * uLoc.x
1489 + sin (uAngle.
theta) * sin (uAngle.
phi) * uLoc.y
1490 + cos (uAngle.
theta) * uLoc.z);
1491 double txPhaseDiff = 2 * M_PI * (sin (sAngle.
theta) * cos (sAngle.
phi) * sLoc.x
1492 + sin (sAngle.
theta) * sin (sAngle.
phi) * sLoc.y
1493 + cos (sAngle.
theta) * sLoc.z);
1495 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1496 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (uAngle.
phi, uAngle.
theta));
1497 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (sAngle.
phi, sAngle.
theta));
1501 ray = (rxFieldPatternTheta * txFieldPatternTheta - rxFieldPatternPhi * txFieldPatternPhi)
1502 * exp (std::complex<double> (0, - 2 * M_PI * dis3D / lambda))
1503 * exp (std::complex<double> (0, rxPhaseDiff))
1504 * exp (std::complex<double> (0, txPhaseDiff));
1506 double K_linear = pow (10,K_factor / 10);
1508 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);
1509 double tempSize = H_usn[uIndex][sIndex].size ();
1510 for (uint8_t nIndex = 1; nIndex < tempSize; nIndex++)
1512 H_usn[uIndex][sIndex][nIndex] *= sqrt (1 / (K_linear + 1));
1520 if (cluster1st == cluster2nd)
1522 clusterDelay.push_back (clusterDelay[cluster1st] + 1.28 * table3gpp->
m_cDS);
1523 clusterDelay.push_back (clusterDelay[cluster1st] + 2.56 * table3gpp->
m_cDS);
1525 clusterAoa.push_back (clusterAoa[cluster1st]);
1526 clusterAoa.push_back (clusterAoa[cluster1st]);
1528 clusterZoa.push_back (clusterZoa[cluster1st]);
1529 clusterZoa.push_back (clusterZoa[cluster1st]);
1531 clusterAod.push_back (clusterAod[cluster1st]);
1532 clusterAod.push_back (clusterAod[cluster1st]);
1534 clusterZod.push_back (clusterZod[cluster1st]);
1535 clusterZod.push_back (clusterZod[cluster1st]);
1540 if (cluster1st < cluster2nd)
1550 clusterDelay.push_back (clusterDelay[
min] + 1.28 * table3gpp->
m_cDS);
1551 clusterDelay.push_back (clusterDelay[
min] + 2.56 * table3gpp->
m_cDS);
1552 clusterDelay.push_back (clusterDelay[
max] + 1.28 * table3gpp->
m_cDS);
1553 clusterDelay.push_back (clusterDelay[
max] + 2.56 * table3gpp->
m_cDS);
1555 clusterAoa.push_back (clusterAoa[
min]);
1556 clusterAoa.push_back (clusterAoa[
min]);
1557 clusterAoa.push_back (clusterAoa[
max]);
1558 clusterAoa.push_back (clusterAoa[
max]);
1560 clusterZoa.push_back (clusterZoa[
min]);
1561 clusterZoa.push_back (clusterZoa[
min]);
1562 clusterZoa.push_back (clusterZoa[
max]);
1563 clusterZoa.push_back (clusterZoa[
max]);
1565 clusterAod.push_back (clusterAod[
min]);
1566 clusterAod.push_back (clusterAod[
min]);
1567 clusterAod.push_back (clusterAod[
max]);
1568 clusterAod.push_back (clusterAod[
max]);
1570 clusterZod.push_back (clusterZod[
min]);
1571 clusterZod.push_back (clusterZod[
min]);
1572 clusterZod.push_back (clusterZod[
max]);
1573 clusterZod.push_back (clusterZod[
max]);
1578 NS_LOG_INFO (
"size of coefficient matrix =[" << H_usn.size () <<
"][" << H_usn[0].size () <<
"][" << H_usn[0][0].size () <<
"]");
1581 channelParams->
m_delay = clusterDelay;
1583 channelParams->
m_angle.clear ();
1584 channelParams->
m_angle.push_back (clusterAoa);
1585 channelParams->
m_angle.push_back (clusterZoa);
1586 channelParams->
m_angle.push_back (clusterAod);
1587 channelParams->
m_angle.push_back (clusterZod);
1589 return channelParams;
1600 uint8_t clusterNum = clusterAOA.size ();
1601 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
1603 powerAttenuation.push_back (0);
1609 double phi_sb, x_sb, theta_sb, y_sb;
1627 if (params->m_nonSelfBlocking.size () == 0)
1637 table.push_back (90);
1639 table.push_back (2);
1644 table.push_back (90);
1645 table.push_back (5);
1646 table.push_back (10);
1648 params->m_nonSelfBlocking.push_back (table);
1653 double deltaX = sqrt (pow (params->m_preLocUT.x - params->m_locUT.x, 2) + pow (params->m_preLocUT.y - params->m_locUT.y, 2));
1679 R = exp (-1 * (deltaX / corrDis + (
Now ().GetSeconds () - params->m_generatedTime.GetSeconds ()) / corrT));
1683 R = exp (-1 * (deltaX / corrDis));
1687 <<
" Time difference:" <<
Now ().GetSeconds () - params->m_generatedTime.GetSeconds ()
1688 <<
" correlation:" << R);
1697 if (R * R * (-0.069) + R * 1.074 - 0.002 < 1)
1699 R = R * R * (-0.069) + R * 1.074 - 0.002;
1705 params->m_nonSelfBlocking[blockInd][
PHI_INDEX] =
1706 R * params->m_nonSelfBlocking[blockInd][
PHI_INDEX] + sqrt (1 - R * R) *
m_normalRv->GetValue ();
1713 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
1715 NS_ASSERT_MSG (clusterAOA[cInd] >= 0 && clusterAOA[cInd] <= 360,
"the AOA should be the range of [0,360]");
1716 NS_ASSERT_MSG (clusterZOA[cInd] >= 0 && clusterZOA[cInd] <= 180,
"the ZOA should be the range of [0,180]");
1719 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phi_sb - x_sb / 2 <<
"," << phi_sb + x_sb / 2 <<
"]");
1720 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << theta_sb - y_sb / 2 <<
"," << theta_sb + y_sb / 2 <<
"]");
1721 if ( std::abs (clusterAOA[cInd] - phi_sb) < (x_sb / 2) && std::abs (clusterZOA[cInd] - theta_sb) < (y_sb / 2))
1723 powerAttenuation[cInd] += 30;
1724 NS_LOG_INFO (
"Cluster[" << (
int)cInd <<
"] is blocked by self blocking region and reduce 30 dB power," 1725 "the attenuation is [" << powerAttenuation[cInd] <<
" dB]");
1729 double phiK, xK, thetaK, yK;
1733 phiK = (0.5 * erfc (-1 * params->m_nonSelfBlocking[blockInd][
PHI_INDEX] / sqrt (2))) * 360;
1744 xK = params->m_nonSelfBlocking[blockInd][
X_INDEX];
1745 thetaK = params->m_nonSelfBlocking[blockInd][
THETA_INDEX];
1746 yK = params->m_nonSelfBlocking[blockInd][
Y_INDEX];
1747 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phiK - xK <<
"," << phiK + xK <<
"]");
1748 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << thetaK - yK <<
"," << thetaK + yK <<
"]");
1750 if ( std::abs (clusterAOA[cInd] - phiK) < (xK)
1751 && std::abs (clusterZOA[cInd] - thetaK) < (yK))
1753 double A1 = clusterAOA[cInd] - (phiK + xK / 2);
1754 double A2 = clusterAOA[cInd] - (phiK - xK / 2);
1755 double Z1 = clusterZOA[cInd] - (thetaK + yK / 2);
1756 double Z2 = clusterZOA[cInd] - (thetaK - yK / 2);
1757 int signA1, signA2, signZ1, signZ2;
1759 if (xK / 2 < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= xK)
1767 if (-1 * xK < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= -1 * xK / 2)
1776 if (yK / 2 < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= yK)
1784 if (-1 * yK < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= -1 * yK / 2)
1793 double F_A1 = atan (signA1 * M_PI / 2 * sqrt (M_PI / lambda *
1794 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (A1 * M_PI / 180) - 1))) / M_PI;
1795 double F_A2 = atan (signA2 * M_PI / 2 * sqrt (M_PI / lambda *
1796 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (A2 * M_PI / 180) - 1))) / M_PI;
1797 double F_Z1 = atan (signZ1 * M_PI / 2 * sqrt (M_PI / lambda *
1798 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (Z1 * M_PI / 180) - 1))) / M_PI;
1799 double F_Z2 = atan (signZ2 * M_PI / 2 * sqrt (M_PI / lambda *
1800 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (Z2 * M_PI / 180) - 1))) / M_PI;
1801 double L_dB = -20 * log10 (1 - (F_A1 + F_A2) * (F_Z1 + F_Z2));
1802 powerAttenuation[cInd] += L_dB;
1803 NS_LOG_INFO (
"Cluster[" << (
int)cInd <<
"] is blocked by no-self blocking, " 1804 "the loss is [" << L_dB <<
"]" <<
" dB");
1809 return powerAttenuation;
1816 for (
auto i = (last-
first) - 1 ; i > 0; --i)
static const double offSetAlpha[20]
static const double sqrtC_UMa_LOS[7][7]
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
TimeWithUnit As(const enum Unit unit) const
Attach a unit to a Time, to facilitate output in a specific unit.
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]
bool m_los
true if LOS, false if NLOS
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 ParamsTable > GetThreeGppTable(bool los, bool o2i, double hBS, double hUT, double distance2D) const
Get the parameters needed to apply the channel generation procedure.
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
bool ChannelMatrixNeedsUpdate(Ptr< const ThreeGppChannelMatrix > channelMatrix, bool isLos) const
Check if the channel matrix has to be updated.
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)
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
static TypeId GetTypeId()
Get the type ID.
#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]
Ptr< ThreeGppChannelMatrix > GetNewChannel(Vector locUT, bool los, bool o2i, 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...
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