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> ();
168 m_normalRv = CreateObject<NormalRandomVariable> ();
189 static TypeId tid =
TypeId (
"ns3::ThreeGppChannelModel")
191 .SetGroupName (
"Spectrum")
193 .AddConstructor<ThreeGppChannelModel> ()
194 .AddAttribute (
"Frequency",
195 "The operating Frequency in Hz",
199 MakeDoubleChecker<double> ())
200 .AddAttribute (
"Scenario",
201 "The 3GPP scenario (RMa, UMa, UMi-StreetCanyon, InH-OfficeOpen, InH-OfficeMixed)",
206 .AddAttribute (
"ChannelConditionModel",
207 "Pointer to the channel condition model",
211 MakePointerChecker<ChannelConditionModel> ())
212 .AddAttribute (
"UpdatePeriod",
213 "Specify the channel coherence time",
218 .AddAttribute (
"Blockage",
219 "Enable blockage model A (sec 7.6.4.1)",
223 .AddAttribute (
"NumNonselfBlocking",
224 "number of non-self-blocking regions",
227 MakeIntegerChecker<uint16_t> ())
228 .AddAttribute (
"PortraitMode",
229 "true for portrait mode, false for landscape mode",
233 .AddAttribute (
"BlockerSpeed",
234 "The speed of moving blockers, the unit is m/s",
237 MakeDoubleChecker<double> ())
260 NS_ASSERT_MSG (
f >= 500.0e6 &&
f <= 100.0e9,
"Frequency should be between 0.5 and 100 GHz but is " <<
f);
275 NS_ASSERT_MSG (scenario ==
"RMa" || scenario ==
"UMa" || scenario ==
"UMi-StreetCanyon" ||
276 scenario ==
"InH-OfficeOpen" || scenario ==
"InH-OfficeMixed",
277 "Unknown scenario, choose between RMa, UMa, UMi-StreetCanyon, InH-OfficeOpen or InH-OfficeMixed");
318 table3gpp->
m_sigLgZSD =
std::max (-1.0, -0.17 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.22);
320 table3gpp->
m_cDS = 3.91e-9;
331 for (uint8_t row = 0; row < 7; row++)
333 for (uint8_t column = 0; column < 7; column++)
339 else if (!los && !o2i)
351 table3gpp->
m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
353 table3gpp->
m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
354 table3gpp->
m_cDS = 3.91e-9;
365 for (uint8_t row = 0; row < 6; row++)
367 for (uint8_t column = 0; column < 6; column++)
385 table3gpp->
m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
387 table3gpp->
m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
388 table3gpp->
m_cDS = 3.91e-9;
399 for (uint8_t row = 0; row < 6; row++)
401 for (uint8_t column = 0; column < 6; column++)
414 table3gpp->
m_uLgDS = -6.955 - 0.0963 * log10 (fcGHz);
416 table3gpp->
m_uLgASD = 1.06 + 0.1114 * log10 (fcGHz);
422 table3gpp->
m_uLgZSD =
std::max (-0.5, -2.1 * distance2D / 1000 - 0.01 * (hUT - 1.5) + 0.75);
425 table3gpp->
m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;
436 for (uint8_t row = 0; row < 7; row++)
438 for (uint8_t column = 0; column < 7; column++)
446 double uLgZSD =
std::max (-0.5, -2.1 * distance2D / 1000 - 0.01 * (hUT - 1.5) + 0.9);
448 double afc = 0.208 * log10 (fcGHz) - 0.782;
450 double cfc = -0.13 * log10 (fcGHz) + 2.03;
451 double efc = 7.66 * log10 (fcGHz) - 5.96;
453 double offsetZOD = efc - std::pow (10, afc * log10 (
std::max (bfc,distance2D)) + cfc);
459 table3gpp->
m_uLgDS = -6.28 - 0.204 * log10 (fcGHz);
461 table3gpp->
m_uLgASD = 1.5 - 0.1144 * log10 (fcGHz);
463 table3gpp->
m_uLgASA = 2.08 - 0.27 * log10 (fcGHz);
465 table3gpp->
m_uLgZSA = -0.3236 * log10 (fcGHz) + 1.512;
470 table3gpp->
m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;;
481 for (uint8_t row = 0; row < 6; row++)
483 for (uint8_t column = 0; column < 6; column++)
504 table3gpp->
m_cDS = 11e-9;
515 for (uint8_t row = 0; row < 6; row++)
517 for (uint8_t column = 0; column < 6; column++)
534 table3gpp->
m_uLgDS = -0.24 * log10 (1 + fcGHz) - 7.14;
536 table3gpp->
m_uLgASD = -0.05 * log10 (1 + fcGHz) + 1.21;
538 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.73;
539 table3gpp->
m_sigLgASA = 0.014 * log10 (1 + fcGHz) + 0.28;
540 table3gpp->
m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73;
541 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34;
542 table3gpp->
m_uLgZSD =
std::max (-0.21, -14.8 * distance2D / 1000 + 0.01 * std::abs (hUT - hBS) + 0.83);
545 table3gpp->
m_cDS = 5e-9;
556 for (uint8_t row = 0; row < 7; row++)
558 for (uint8_t column = 0; column < 7; column++)
566 double uLgZSD =
std::max (-0.5, -3.1 * distance2D / 1000 + 0.01 *
std::max (hUT - hBS,0.0) + 0.2);
567 double offsetZOD = -1 * std::pow (10, -1.5 * log10 (
std::max (10.0, distance2D)) + 3.3);
572 table3gpp->
m_uLgDS = -0.24 * log10 (1 + fcGHz) - 6.83;
573 table3gpp->
m_sigLgDS = 0.16 * log10 (1 + fcGHz) + 0.28;
574 table3gpp->
m_uLgASD = -0.23 * log10 (1 + fcGHz) + 1.53;
575 table3gpp->
m_sigLgASD = 0.11 * log10 (1 + fcGHz) + 0.33;
576 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
577 table3gpp->
m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
578 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
579 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
583 table3gpp->
m_cDS = 11e-9;
594 for (uint8_t row = 0; row < 6; row++)
596 for (uint8_t column = 0; column < 6; column++)
617 table3gpp->
m_cDS = 11e-9;
628 for (uint8_t row = 0; row < 6; row++)
630 for (uint8_t column = 0; column < 6; column++)
640 NS_ASSERT_MSG (!o2i,
"The indoor scenario does out support outdoor to indoor");
645 table3gpp->
m_uLgDS = -0.01 * log10 (1 + fcGHz) - 7.692;
649 table3gpp->
m_uLgASA = -0.19 * log10 (1 + fcGHz) + 1.781;
650 table3gpp->
m_sigLgASA = 0.12 * log10 (1 + fcGHz) + 0.119;
651 table3gpp->
m_uLgZSA = -0.26 * log10 (1 + fcGHz) + 1.44;
652 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.264;
653 table3gpp->
m_uLgZSD = -1.43 * log10 (1 + fcGHz) + 2.228;
654 table3gpp->
m_sigLgZSD = 0.13 * log10 (1 + fcGHz) + 0.30;
656 table3gpp->
m_cDS = 3.91e-9;
667 for (uint8_t row = 0; row < 7; row++)
669 for (uint8_t column = 0; column < 7; column++)
679 table3gpp->
m_uLgDS = -0.28 * log10 (1 + fcGHz) - 7.173;
680 table3gpp->
m_sigLgDS = 0.1 * log10 (1 + fcGHz) + 0.055;
683 table3gpp->
m_uLgASA = -0.11 * log10 (1 + fcGHz) + 1.863;
684 table3gpp->
m_sigLgASA = 0.12 * log10 (1 + fcGHz) + 0.059;
685 table3gpp->
m_uLgZSA = -0.15 * log10 (1 + fcGHz) + 1.387;
686 table3gpp->
m_sigLgZSA = -0.09 * log10 (1 + fcGHz) + 0.746;
690 table3gpp->
m_cDS = 3.91e-9;
701 for (uint8_t row = 0; row < 6; row++)
703 for (uint8_t column = 0; column < 6; column++)
726 if (channelMatrix->
m_los != los)
728 NS_LOG_DEBUG (
"old los condition " << channelMatrix->
m_los <<
" new los condition " << los);
753 uint32_t channelId =
GetKey (x1, x2);
757 bool los = (condition->GetLosCondition () == ChannelCondition::LosConditionValue::LOS);
763 bool notFound =
false;
782 if (notFound || update)
785 Angles txAngle (bMob->GetPosition (), aMob->GetPosition ());
786 Angles rxAngle (aMob->GetPosition (), bMob->GetPosition ());
788 double x = aMob->GetPosition ().x - bMob->GetPosition ().x;
789 double y = aMob->GetPosition ().y - bMob->GetPosition ().y;
790 double distance2D = sqrt (
x *
x + y * y);
794 double hUt =
std::min (aMob->GetPosition ().z, bMob->GetPosition ().z);
795 double hBs =
std::max (aMob->GetPosition ().z, bMob->GetPosition ().z);
801 Vector locUt = Vector (0.0, 0.0, 0.0);
803 channelMatrix =
GetNewChannel (locUt, los, o2i, aAntenna, bAntenna, rxAngle, txAngle, distance2D, hBs, hUt);
804 channelMatrix->
m_nodeIds = std::make_pair (aMob->GetObject<
Node> ()->
GetId (), bMob->GetObject<
Node> ()->GetId ());
810 return channelMatrix;
818 double dis2D,
double hBS,
double hUT)
const 833 channelParams->
m_los = los;
834 channelParams->
m_o2i = o2i;
838 double dis3D = std::sqrt (dis2D * dis2D + (hBS - hUT) * (hBS - hUT));
852 for (uint8_t iter = 0; iter < paramNum; iter++)
854 LSPsIndep.push_back (
m_normalRv->GetValue ());
856 for (uint8_t row = 0; row < paramNum; row++)
859 for (uint8_t column = 0; column < paramNum; column++)
861 temp += table3gpp->
m_sqrtC[row][column] * LSPsIndep[column];
863 LSPs.push_back (temp);
868 double DS,ASD,ASA,ZSA,ZSD,K_factor = 0;
871 K_factor = LSPs[1] * table3gpp->
m_sigK + table3gpp->
m_uK;
892 channelParams->
m_DS = DS;
893 channelParams->
m_K = K_factor;
895 NS_LOG_INFO (
"K-factor=" << K_factor <<
",DS=" << DS <<
", ASD=" << ASD <<
", ASA=" << ASA <<
", ZSD=" << ZSD <<
", ZSA=" << ZSA);
899 double minTau = 100.0;
900 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
907 clusterDelay.push_back (tau);
910 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
912 clusterDelay[cIndex] -= minTau;
914 std::sort (clusterDelay.begin (), clusterDelay.end ());
922 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
924 double power = exp (-1 * clusterDelay[cIndex] * (table3gpp->
m_rTau - 1) / table3gpp->
m_rTau / DS) *
927 clusterPower.push_back (power);
931 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
933 clusterPower[cIndex] = clusterPower[cIndex] / powerSum;
939 double K_linear = pow (10,K_factor / 10);
941 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
945 clusterPowerForAngles.push_back (clusterPower[cIndex] / (1 + K_linear) + K_linear / (1 + K_linear));
949 clusterPowerForAngles.push_back (clusterPower[cIndex] / (1 + K_linear));
951 if (powerMax < clusterPowerForAngles[cIndex])
953 powerMax = clusterPowerForAngles[cIndex];
959 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
961 clusterPowerForAngles.push_back (clusterPower[cIndex]);
962 if (powerMax < clusterPowerForAngles[cIndex])
964 powerMax = clusterPowerForAngles[cIndex];
971 double thresh = 0.0032;
972 for (uint8_t cIndex = numOfCluster; cIndex > 0; cIndex--)
974 if (clusterPowerForAngles[cIndex - 1] < thresh * powerMax )
976 clusterPowerForAngles.erase (clusterPowerForAngles.begin () + cIndex - 1);
977 clusterPower.erase (clusterPower.begin () + cIndex - 1);
978 clusterDelay.erase (clusterDelay.begin () + cIndex - 1);
981 uint8_t numReducedCluster = clusterPower.size ();
987 double C_tau = 0.7705 - 0.0433 * K_factor + 2e-4 * pow (K_factor,2) + 17e-6 * pow (K_factor,3);
988 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
990 clusterDelay[cIndex] = clusterDelay[cIndex] / C_tau;
996 double C_NLOS, C_phi;
999 switch (numOfCluster)
1040 C_phi = C_NLOS * (1.1035 - 0.028 * K_factor - 2e-3 * pow (K_factor,2) + 1e-4 * pow (K_factor,3));
1048 switch (numOfCluster)
1077 C_theta = C_NLOS * (1.3086 + 0.0339 * K_factor - 0.0077 * pow (K_factor,2) + 2e-4 * pow (K_factor,3));
1085 DoubleVector clusterAoa, clusterAod, clusterZoa, clusterZod;
1087 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1089 angle = 2*ASA*sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi;
1090 clusterAoa.push_back (angle);
1091 angle = 2*ASD*sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi;
1092 clusterAod.push_back (angle);
1093 angle = -1*ZSA*log (clusterPowerForAngles[cIndex] / powerMax) / C_theta;
1094 clusterZoa.push_back (angle);
1095 angle = -1*ZSD*log (clusterPowerForAngles[cIndex] / powerMax) / C_theta;
1096 clusterZod.push_back (angle);
1099 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1106 clusterAoa[cIndex] = clusterAoa[cIndex] * Xn + (
m_normalRv->GetValue () * ASA / 7) + uAngle.
phi * 180 / M_PI;
1107 clusterAod[cIndex] = clusterAod[cIndex] * Xn + (
m_normalRv->GetValue () * ASD / 7) + sAngle.
phi * 180 / M_PI;
1110 clusterZoa[cIndex] = clusterZoa[cIndex] * Xn + (
m_normalRv->GetValue () * ZSA / 7) + 90;
1114 clusterZoa[cIndex] = clusterZoa[cIndex] * Xn + (
m_normalRv->GetValue () * ZSA / 7) + uAngle.
theta * 180 / M_PI;
1116 clusterZod[cIndex] = clusterZod[cIndex] * Xn + (
m_normalRv->GetValue () * ZSD / 7) + sAngle.
theta * 180 / M_PI + table3gpp->
m_offsetZOD;
1124 double diffAoa = clusterAoa[0] - uAngle.
phi * 180 / M_PI;
1125 double diffAod = clusterAod[0] - sAngle.
phi * 180 / M_PI;
1126 double diffZsa = clusterZoa[0] - uAngle.
theta * 180 / M_PI;
1127 double diffZsd = clusterZod[0] - sAngle.
theta * 180 / M_PI;
1129 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1131 clusterAoa[cIndex] -= diffAoa;
1132 clusterAod[cIndex] -= diffAod;
1133 clusterZoa[cIndex] -= diffZsa;
1134 clusterZod[cIndex] -= diffZsd;
1139 double rayAoa_radian[numReducedCluster][raysPerCluster];
1140 double rayAod_radian[numReducedCluster][raysPerCluster];
1141 double rayZoa_radian[numReducedCluster][raysPerCluster];
1142 double rayZod_radian[numReducedCluster][raysPerCluster];
1144 for (uint8_t nInd = 0; nInd < numReducedCluster; nInd++)
1146 for (uint8_t mInd = 0; mInd < raysPerCluster; mInd++)
1149 while (tempAoa > 360)
1159 NS_ASSERT_MSG (tempAoa >= 0 && tempAoa <= 360,
"the AOA should be the range of [0,360]");
1160 rayAoa_radian[nInd][mInd] = tempAoa * M_PI / 180;
1163 while (tempAod > 360)
1172 NS_ASSERT_MSG (tempAod >= 0 && tempAod <= 360,
"the AOD should be the range of [0,360]");
1173 rayAod_radian[nInd][mInd] = tempAod * M_PI / 180;
1177 while (tempZoa > 360)
1189 tempZoa = 360 - tempZoa;
1192 NS_ASSERT_MSG (tempZoa >= 0&&tempZoa <= 180,
"the ZOA should be the range of [0,180]");
1193 rayZoa_radian[nInd][mInd] = tempZoa * M_PI / 180;
1195 double tempZod = clusterZod[nInd] + 0.375 * pow (10,table3gpp->
m_uLgZSD) *
offSetAlpha[mInd];
1197 while (tempZod > 360)
1208 tempZod = 360 - tempZod;
1210 NS_ASSERT_MSG (tempZod >= 0&&tempZod <= 180,
"the ZOD should be the range of [0,180]");
1211 rayZod_radian[nInd][mInd] = tempZod * M_PI / 180;
1215 double sizeTemp = clusterZoa.size ();
1216 for (uint8_t ind = 0; ind < 4; ind++)
1221 angle_degree = clusterAoa;
1224 angle_degree = clusterZoa;
1227 angle_degree = clusterAod;
1230 angle_degree = clusterZod;
1236 for (uint8_t nIndex = 0; nIndex < sizeTemp; nIndex++)
1238 while (angle_degree[nIndex] > 360)
1240 angle_degree[nIndex] -= 360;
1243 while (angle_degree[nIndex] < 0)
1245 angle_degree[nIndex] += 360;
1248 if (ind == 1 || ind == 3)
1250 if (angle_degree[nIndex] > 180)
1252 angle_degree[nIndex] = 360 - angle_degree[nIndex];
1259 clusterAoa = angle_degree;
1262 clusterZoa = angle_degree;
1265 clusterAod = angle_degree;
1268 clusterZod = angle_degree;
1279 for (uint8_t cInd = 0; cInd < numReducedCluster; cInd++)
1281 clusterPower[cInd] = clusterPower[cInd] / pow (10,attenuation_dB[cInd] / 10);
1286 attenuation_dB.push_back (0);
1291 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1293 std::shuffle (&rayAod_radian[cIndex][0],&rayAod_radian[cIndex][raysPerCluster],std::default_random_engine (cIndex * 1000 + 100));
1294 std::shuffle (&rayAoa_radian[cIndex][0],&rayAoa_radian[cIndex][raysPerCluster],std::default_random_engine (cIndex * 1000 + 200));
1295 std::shuffle (&rayZod_radian[cIndex][0],&rayZod_radian[cIndex][raysPerCluster],std::default_random_engine (cIndex * 1000 + 300));
1296 std::shuffle (&rayZoa_radian[cIndex][0],&rayZoa_radian[cIndex][raysPerCluster],std::default_random_engine (cIndex * 1000 + 400));
1303 for (uint8_t nInd = 0; nInd < numReducedCluster; nInd++)
1307 for (uint8_t mInd = 0; mInd < raysPerCluster; mInd++)
1309 double uXprLinear = pow (10, table3gpp->
m_uXpr / 10);
1310 double sigXprLinear = pow (10, table3gpp->
m_sigXpr / 10);
1312 temp.push_back (std::pow (10, (
m_normalRv->GetValue () * sigXprLinear + uXprLinear) / 10));
1314 for (uint8_t pInd = 0; pInd < 4; pInd++)
1318 temp2.push_back (temp3);
1320 crossPolarizationPowerRatios.push_back (temp);
1321 clusterPhase.push_back (temp2);
1330 uint64_t uSize = uAntenna->GetNumberOfElements ();
1331 uint64_t sSize = sAntenna->GetNumberOfElements ();
1333 uint8_t cluster1st = 0, cluster2nd = 0;
1334 double maxPower = 0;
1335 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1337 if (maxPower < clusterPower[cIndex])
1339 maxPower = clusterPower[cIndex];
1340 cluster1st = cIndex;
1344 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1346 if (maxPower < clusterPower[cIndex] && cluster1st != cIndex)
1348 maxPower = clusterPower[cIndex];
1349 cluster2nd = cIndex;
1353 NS_LOG_INFO (
"1st strongest cluster:" << (
int)cluster1st <<
", 2nd strongest cluster:" << (
int)cluster2nd);
1359 H_usn.resize (uSize);
1360 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1362 H_usn[uIndex].resize (sSize);
1363 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1365 H_usn[uIndex][sIndex].resize (numReducedCluster);
1370 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1372 Vector uLoc = uAntenna->GetElementLocation (uIndex);
1374 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1377 Vector sLoc = sAntenna->GetElementLocation (sIndex);
1379 for (uint8_t nIndex = 0; nIndex < numReducedCluster; nIndex++)
1382 if (nIndex != cluster1st && nIndex != cluster2nd)
1384 std::complex<double> rays (0,0);
1385 for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++)
1387 DoubleVector initialPhase = clusterPhase[nIndex][mIndex];
1388 double k = crossPolarizationPowerRatios[nIndex][mIndex];
1390 double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x
1391 + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y
1392 + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z);
1394 double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x
1395 + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y
1396 + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z);
1399 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1400 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (rayAoa_radian[nIndex][mIndex], rayZoa_radian[nIndex][mIndex]));
1401 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (rayAod_radian[nIndex][mIndex], rayZod_radian[nIndex][mIndex]));
1403 rays += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1404 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1405 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1406 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1407 * exp (std::complex<double> (0, rxPhaseDiff))
1408 * exp (std::complex<double> (0, txPhaseDiff));
1410 rays *= sqrt (clusterPower[nIndex] / raysPerCluster);
1411 H_usn[uIndex][sIndex][nIndex] = rays;
1415 std::complex<double> raysSub1 (0,0);
1416 std::complex<double> raysSub2 (0,0);
1417 std::complex<double> raysSub3 (0,0);
1419 for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++)
1421 double k = crossPolarizationPowerRatios[nIndex][mIndex];
1425 DoubleVector initialPhase = clusterPhase[nIndex][mIndex];
1426 double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x
1427 + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y
1428 + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z);
1429 double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x
1430 + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y
1431 + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z);
1433 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1434 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (rayAoa_radian[nIndex][mIndex], rayZoa_radian[nIndex][mIndex]));
1435 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (rayAod_radian[nIndex][mIndex], rayZod_radian[nIndex][mIndex]));
1445 raysSub2 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1446 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1447 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1448 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1449 * exp (std::complex<double> (0, rxPhaseDiff))
1450 * exp (std::complex<double> (0, txPhaseDiff));
1456 raysSub3 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1457 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1458 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1459 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1460 * exp (std::complex<double> (0, rxPhaseDiff))
1461 * exp (std::complex<double> (0, txPhaseDiff));
1464 raysSub1 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1465 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
1466 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
1467 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1468 * exp (std::complex<double> (0, rxPhaseDiff))
1469 * exp (std::complex<double> (0, txPhaseDiff));
1473 raysSub1 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1474 raysSub2 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1475 raysSub3 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1476 H_usn[uIndex][sIndex][nIndex] = raysSub1;
1477 H_usn[uIndex][sIndex].push_back (raysSub2);
1478 H_usn[uIndex][sIndex].push_back (raysSub3);
1484 std::complex<double> ray (0,0);
1485 double rxPhaseDiff = 2 * M_PI * (sin (uAngle.
theta) * cos (uAngle.
phi) * uLoc.x
1486 + sin (uAngle.
theta) * sin (uAngle.
phi) * uLoc.y
1487 + cos (uAngle.
theta) * uLoc.z);
1488 double txPhaseDiff = 2 * M_PI * (sin (sAngle.
theta) * cos (sAngle.
phi) * sLoc.x
1489 + sin (sAngle.
theta) * sin (sAngle.
phi) * sLoc.y
1490 + cos (sAngle.
theta) * sLoc.z);
1492 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1493 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (uAngle.
phi, uAngle.
theta));
1494 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (sAngle.
phi, sAngle.
theta));
1498 ray = (rxFieldPatternTheta * txFieldPatternTheta - rxFieldPatternPhi * txFieldPatternPhi)
1499 * exp (std::complex<double> (0, - 2 * M_PI * dis3D / lambda))
1500 * exp (std::complex<double> (0, rxPhaseDiff))
1501 * exp (std::complex<double> (0, txPhaseDiff));
1503 double K_linear = pow (10,K_factor / 10);
1505 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);
1506 double tempSize = H_usn[uIndex][sIndex].size ();
1507 for (uint8_t nIndex = 1; nIndex < tempSize; nIndex++)
1509 H_usn[uIndex][sIndex][nIndex] *= sqrt (1 / (K_linear + 1));
1517 if (cluster1st == cluster2nd)
1519 clusterDelay.push_back (clusterDelay[cluster1st] + 1.28 * table3gpp->
m_cDS);
1520 clusterDelay.push_back (clusterDelay[cluster1st] + 2.56 * table3gpp->
m_cDS);
1522 clusterAoa.push_back (clusterAoa[cluster1st]);
1523 clusterAoa.push_back (clusterAoa[cluster1st]);
1525 clusterZoa.push_back (clusterZoa[cluster1st]);
1526 clusterZoa.push_back (clusterZoa[cluster1st]);
1528 clusterAod.push_back (clusterAod[cluster1st]);
1529 clusterAod.push_back (clusterAod[cluster1st]);
1531 clusterZod.push_back (clusterZod[cluster1st]);
1532 clusterZod.push_back (clusterZod[cluster1st]);
1537 if (cluster1st < cluster2nd)
1547 clusterDelay.push_back (clusterDelay[
min] + 1.28 * table3gpp->
m_cDS);
1548 clusterDelay.push_back (clusterDelay[
min] + 2.56 * table3gpp->
m_cDS);
1549 clusterDelay.push_back (clusterDelay[
max] + 1.28 * table3gpp->
m_cDS);
1550 clusterDelay.push_back (clusterDelay[
max] + 2.56 * table3gpp->
m_cDS);
1552 clusterAoa.push_back (clusterAoa[
min]);
1553 clusterAoa.push_back (clusterAoa[
min]);
1554 clusterAoa.push_back (clusterAoa[
max]);
1555 clusterAoa.push_back (clusterAoa[
max]);
1557 clusterZoa.push_back (clusterZoa[
min]);
1558 clusterZoa.push_back (clusterZoa[
min]);
1559 clusterZoa.push_back (clusterZoa[
max]);
1560 clusterZoa.push_back (clusterZoa[
max]);
1562 clusterAod.push_back (clusterAod[
min]);
1563 clusterAod.push_back (clusterAod[
min]);
1564 clusterAod.push_back (clusterAod[
max]);
1565 clusterAod.push_back (clusterAod[
max]);
1567 clusterZod.push_back (clusterZod[
min]);
1568 clusterZod.push_back (clusterZod[
min]);
1569 clusterZod.push_back (clusterZod[
max]);
1570 clusterZod.push_back (clusterZod[
max]);
1575 NS_LOG_INFO (
"size of coefficient matrix =[" << H_usn.size () <<
"][" << H_usn[0].size () <<
"][" << H_usn[0][0].size () <<
"]");
1578 channelParams->
m_delay = clusterDelay;
1580 channelParams->
m_angle.clear ();
1581 channelParams->
m_angle.push_back (clusterAoa);
1582 channelParams->
m_angle.push_back (clusterZoa);
1583 channelParams->
m_angle.push_back (clusterAod);
1584 channelParams->
m_angle.push_back (clusterZod);
1586 return channelParams;
1597 uint8_t clusterNum = clusterAOA.size ();
1598 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
1600 powerAttenuation.push_back (0);
1606 double phi_sb, x_sb, theta_sb, y_sb;
1624 if (params->m_nonSelfBlocking.size () == 0)
1634 table.push_back (90);
1636 table.push_back (2);
1641 table.push_back (90);
1642 table.push_back (5);
1643 table.push_back (10);
1645 params->m_nonSelfBlocking.push_back (table);
1650 double deltaX = sqrt (pow (params->m_preLocUT.x - params->m_locUT.x, 2) + pow (params->m_preLocUT.y - params->m_locUT.y, 2));
1676 R = exp (-1 * (deltaX / corrDis + (
Now ().GetSeconds () - params->m_generatedTime.GetSeconds ()) / corrT));
1680 R = exp (-1 * (deltaX / corrDis));
1684 <<
" Time difference:" <<
Now ().GetSeconds () - params->m_generatedTime.GetSeconds ()
1685 <<
" correlation:" << R);
1694 if (R * R * (-0.069) + R * 1.074 - 0.002 < 1)
1696 R = R * R * (-0.069) + R * 1.074 - 0.002;
1702 params->m_nonSelfBlocking[blockInd][
PHI_INDEX] =
1703 R * params->m_nonSelfBlocking[blockInd][
PHI_INDEX] + sqrt (1 - R * R) *
m_normalRv->GetValue ();
1710 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
1712 NS_ASSERT_MSG (clusterAOA[cInd] >= 0 && clusterAOA[cInd] <= 360,
"the AOA should be the range of [0,360]");
1713 NS_ASSERT_MSG (clusterZOA[cInd] >= 0 && clusterZOA[cInd] <= 180,
"the ZOA should be the range of [0,180]");
1716 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phi_sb - x_sb / 2 <<
"," << phi_sb + x_sb / 2 <<
"]");
1717 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << theta_sb - y_sb / 2 <<
"," << theta_sb + y_sb / 2 <<
"]");
1718 if ( std::abs (clusterAOA[cInd] - phi_sb) < (x_sb / 2) && std::abs (clusterZOA[cInd] - theta_sb) < (y_sb / 2))
1720 powerAttenuation[cInd] += 30;
1721 NS_LOG_INFO (
"Cluster[" << (
int)cInd <<
"] is blocked by self blocking region and reduce 30 dB power," 1722 "the attenuation is [" << powerAttenuation[cInd] <<
" dB]");
1726 double phiK, xK, thetaK, yK;
1730 phiK = (0.5 * erfc (-1 * params->m_nonSelfBlocking[blockInd][
PHI_INDEX] / sqrt (2))) * 360;
1741 xK = params->m_nonSelfBlocking[blockInd][
X_INDEX];
1742 thetaK = params->m_nonSelfBlocking[blockInd][
THETA_INDEX];
1743 yK = params->m_nonSelfBlocking[blockInd][
Y_INDEX];
1744 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phiK - xK <<
"," << phiK + xK <<
"]");
1745 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << thetaK - yK <<
"," << thetaK + yK <<
"]");
1747 if ( std::abs (clusterAOA[cInd] - phiK) < (xK)
1748 && std::abs (clusterZOA[cInd] - thetaK) < (yK))
1750 double A1 = clusterAOA[cInd] - (phiK + xK / 2);
1751 double A2 = clusterAOA[cInd] - (phiK - xK / 2);
1752 double Z1 = clusterZOA[cInd] - (thetaK + yK / 2);
1753 double Z2 = clusterZOA[cInd] - (thetaK - yK / 2);
1754 int signA1, signA2, signZ1, signZ2;
1756 if (xK / 2 < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= xK)
1764 if (-1 * xK < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= -1 * xK / 2)
1773 if (yK / 2 < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= yK)
1781 if (-1 * yK < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= -1 * yK / 2)
1790 double F_A1 = atan (signA1 * M_PI / 2 * sqrt (M_PI / lambda *
1791 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (A1 * M_PI / 180) - 1))) / M_PI;
1792 double F_A2 = atan (signA2 * M_PI / 2 * sqrt (M_PI / lambda *
1793 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (A2 * M_PI / 180) - 1))) / M_PI;
1794 double F_Z1 = atan (signZ1 * M_PI / 2 * sqrt (M_PI / lambda *
1795 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (Z1 * M_PI / 180) - 1))) / M_PI;
1796 double F_Z2 = atan (signZ2 * M_PI / 2 * sqrt (M_PI / lambda *
1797 params->m_nonSelfBlocking[blockInd][
R_INDEX] * (1 / cos (Z2 * M_PI / 180) - 1))) / M_PI;
1798 double L_dB = -20 * log10 (1 - (F_A1 + F_A2) * (F_Z1 + F_Z2));
1799 powerAttenuation[cInd] += L_dB;
1800 NS_LOG_INFO (
"Cluster[" << (
int)cInd <<
"] is blocked by no-self blocking, " 1801 "the loss is [" << L_dB <<
"]" <<
" dB");
1806 return powerAttenuation;
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.
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
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.
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]
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...
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>.
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
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
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
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