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 ();
313 table3gpp->m_numOfCluster = 11;
314 table3gpp->m_raysPerCluster = 20;
315 table3gpp->m_uLgDS = -7.49;
316 table3gpp->m_sigLgDS = 0.55;
317 table3gpp->m_uLgASD = 0.90;
318 table3gpp->m_sigLgASD = 0.38;
319 table3gpp->m_uLgASA = 1.52;
320 table3gpp->m_sigLgASA = 0.24;
321 table3gpp->m_uLgZSA = 0.47;
322 table3gpp->m_sigLgZSA = 0.40;
323 table3gpp->m_uLgZSD = 0.34;
324 table3gpp->m_sigLgZSD =
std::max (-1.0, -0.17 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.22);
325 table3gpp->m_offsetZOD = 0;
326 table3gpp->m_cDS = 3.91e-9;
327 table3gpp->m_cASD = 2;
328 table3gpp->m_cASA = 3;
329 table3gpp->m_cZSA = 3;
331 table3gpp->m_sigK = 4;
332 table3gpp->m_rTau = 3.8;
333 table3gpp->m_uXpr = 12;
334 table3gpp->m_sigXpr = 4;
335 table3gpp->m_perClusterShadowingStd = 3;
337 for (uint8_t row = 0; row < 7; row++)
339 for (uint8_t column = 0; column < 7; column++)
341 table3gpp->m_sqrtC[row][column] =
sqrtC_RMa_LOS[row][column];
345 else if (!los && !o2i)
347 table3gpp->m_numOfCluster = 10;
348 table3gpp->m_raysPerCluster = 20;
349 table3gpp->m_uLgDS = -7.43;
350 table3gpp->m_sigLgDS = 0.48;
351 table3gpp->m_uLgASD = 0.95;
352 table3gpp->m_sigLgASD = 0.45;
353 table3gpp->m_uLgASA = 1.52;
354 table3gpp->m_sigLgASA = 0.13;
355 table3gpp->m_uLgZSA = 0.58,
356 table3gpp->m_sigLgZSA = 0.37;
357 table3gpp->m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
358 table3gpp->m_sigLgZSD = 0.30;
359 table3gpp->m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
360 table3gpp->m_cDS = 3.91e-9;
361 table3gpp->m_cASD = 2;
362 table3gpp->m_cASA = 3;
363 table3gpp->m_cZSA = 3;
365 table3gpp->m_sigK = 0;
366 table3gpp->m_rTau = 1.7;
367 table3gpp->m_uXpr = 7;
368 table3gpp->m_sigXpr = 3;
369 table3gpp->m_perClusterShadowingStd = 3;
371 for (uint8_t row = 0; row < 6; row++)
373 for (uint8_t column = 0; column < 6; column++)
381 table3gpp->m_numOfCluster = 10;
382 table3gpp->m_raysPerCluster = 20;
383 table3gpp->m_uLgDS = -7.47;
384 table3gpp->m_sigLgDS = 0.24;
385 table3gpp->m_uLgASD = 0.67;
386 table3gpp->m_sigLgASD = 0.18;
387 table3gpp->m_uLgASA = 1.66;
388 table3gpp->m_sigLgASA = 0.21;
389 table3gpp->m_uLgZSA = 0.93,
390 table3gpp->m_sigLgZSA = 0.22;
391 table3gpp->m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
392 table3gpp->m_sigLgZSD = 0.30;
393 table3gpp->m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
394 table3gpp->m_cDS = 3.91e-9;
395 table3gpp->m_cASD = 2;
396 table3gpp->m_cASA = 3;
397 table3gpp->m_cZSA = 3;
399 table3gpp->m_sigK = 0;
400 table3gpp->m_rTau = 1.7;
401 table3gpp->m_uXpr = 7;
402 table3gpp->m_sigXpr = 3;
403 table3gpp->m_perClusterShadowingStd = 3;
405 for (uint8_t row = 0; row < 6; row++)
407 for (uint8_t column = 0; column < 6; column++)
409 table3gpp->m_sqrtC[row][column] =
sqrtC_RMa_O2I[row][column];
418 table3gpp->m_numOfCluster = 12;
419 table3gpp->m_raysPerCluster = 20;
420 table3gpp->m_uLgDS = -6.955 - 0.0963 * log10 (fcGHz);
421 table3gpp->m_sigLgDS = 0.66;
422 table3gpp->m_uLgASD = 1.06 + 0.1114 * log10 (fcGHz);
423 table3gpp->m_sigLgASD = 0.28;
424 table3gpp->m_uLgASA = 1.81;
425 table3gpp->m_sigLgASA = 0.20;
426 table3gpp->m_uLgZSA = 0.95;
427 table3gpp->m_sigLgZSA = 0.16;
428 table3gpp->m_uLgZSD =
std::max (-0.5, -2.1 * distance2D / 1000 - 0.01 * (hUT - 1.5) + 0.75);
429 table3gpp->m_sigLgZSD = 0.40;
430 table3gpp->m_offsetZOD = 0;
431 table3gpp->m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;
432 table3gpp->m_cASD = 5;
433 table3gpp->m_cASA = 11;
434 table3gpp->m_cZSA = 7;
436 table3gpp->m_sigK = 3.5;
437 table3gpp->m_rTau = 2.5;
438 table3gpp->m_uXpr = 8;
439 table3gpp->m_sigXpr = 4;
440 table3gpp->m_perClusterShadowingStd = 3;
442 for (uint8_t row = 0; row < 7; row++)
444 for (uint8_t column = 0; column < 7; column++)
446 table3gpp->m_sqrtC[row][column] =
sqrtC_UMa_LOS[row][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);
463 table3gpp->m_numOfCluster = 20;
464 table3gpp->m_raysPerCluster = 20;
465 table3gpp->m_uLgDS = -6.28 - 0.204 * log10 (fcGHz);
466 table3gpp->m_sigLgDS = 0.39;
467 table3gpp->m_uLgASD = 1.5 - 0.1144 * log10 (fcGHz);
468 table3gpp->m_sigLgASD = 0.28;
469 table3gpp->m_uLgASA = 2.08 - 0.27 * log10 (fcGHz);
470 table3gpp->m_sigLgASA = 0.11;
471 table3gpp->m_uLgZSA = -0.3236 * log10 (fcGHz) + 1.512;
472 table3gpp->m_sigLgZSA = 0.16;
473 table3gpp->m_uLgZSD = uLgZSD;
474 table3gpp->m_sigLgZSD = 0.49;
475 table3gpp->m_offsetZOD = offsetZOD;
476 table3gpp->m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;
477 table3gpp->m_cASD = 2;
478 table3gpp->m_cASA = 15;
479 table3gpp->m_cZSA = 7;
481 table3gpp->m_sigK = 0;
482 table3gpp->m_rTau = 2.3;
483 table3gpp->m_uXpr = 7;
484 table3gpp->m_sigXpr = 3;
485 table3gpp->m_perClusterShadowingStd = 3;
487 for (uint8_t row = 0; row < 6; row++)
489 for (uint8_t column = 0; column < 6; column++)
497 table3gpp->m_numOfCluster = 12;
498 table3gpp->m_raysPerCluster = 20;
499 table3gpp->m_uLgDS = -6.62;
500 table3gpp->m_sigLgDS = 0.32;
501 table3gpp->m_uLgASD = 1.25;
502 table3gpp->m_sigLgASD = 0.42;
503 table3gpp->m_uLgASA = 1.76;
504 table3gpp->m_sigLgASA = 0.16;
505 table3gpp->m_uLgZSA = 1.01;
506 table3gpp->m_sigLgZSA = 0.43;
507 table3gpp->m_uLgZSD = uLgZSD;
508 table3gpp->m_sigLgZSD = 0.49;
509 table3gpp->m_offsetZOD = offsetZOD;
510 table3gpp->m_cDS = 11e-9;
511 table3gpp->m_cASD = 5;
512 table3gpp->m_cASA = 8;
513 table3gpp->m_cZSA = 3;
515 table3gpp->m_sigK = 0;
516 table3gpp->m_rTau = 2.2;
517 table3gpp->m_uXpr = 9;
518 table3gpp->m_sigXpr = 5;
519 table3gpp->m_perClusterShadowingStd = 4;
521 for (uint8_t row = 0; row < 6; row++)
523 for (uint8_t column = 0; column < 6; column++)
525 table3gpp->m_sqrtC[row][column] =
sqrtC_UMa_O2I[row][column];
538 table3gpp->m_numOfCluster = 12;
539 table3gpp->m_raysPerCluster = 20;
540 table3gpp->m_uLgDS = -0.24 * log10 (1 + fcGHz) - 7.14;
541 table3gpp->m_sigLgDS = 0.38;
542 table3gpp->m_uLgASD = -0.05 * log10 (1 + fcGHz) + 1.21;
543 table3gpp->m_sigLgASD = 0.41;
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);
549 table3gpp->m_sigLgZSD = 0.35;
550 table3gpp->m_offsetZOD = 0;
551 table3gpp->m_cDS = 5e-9;
552 table3gpp->m_cASD = 3;
553 table3gpp->m_cASA = 17;
554 table3gpp->m_cZSA = 7;
556 table3gpp->m_sigK = 5;
557 table3gpp->m_rTau = 3;
558 table3gpp->m_uXpr = 9;
559 table3gpp->m_sigXpr = 3;
560 table3gpp->m_perClusterShadowingStd = 3;
562 for (uint8_t row = 0; row < 7; row++)
564 for (uint8_t column = 0; column < 7; column++)
566 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_LOS[row][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);
576 table3gpp->m_numOfCluster = 19;
577 table3gpp->m_raysPerCluster = 20;
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;
586 table3gpp->m_uLgZSD = uLgZSD;
587 table3gpp->m_sigLgZSD = 0.35;
588 table3gpp->m_offsetZOD = offsetZOD;
589 table3gpp->m_cDS = 11e-9;
590 table3gpp->m_cASD = 10;
591 table3gpp->m_cASA = 22;
592 table3gpp->m_cZSA = 7;
594 table3gpp->m_sigK = 0;
595 table3gpp->m_rTau = 2.1;
596 table3gpp->m_uXpr = 8;
597 table3gpp->m_sigXpr = 3;
598 table3gpp->m_perClusterShadowingStd = 3;
600 for (uint8_t row = 0; row < 6; row++)
602 for (uint8_t column = 0; column < 6; column++)
610 table3gpp->m_numOfCluster = 12;
611 table3gpp->m_raysPerCluster = 20;
612 table3gpp->m_uLgDS = -6.62;
613 table3gpp->m_sigLgDS = 0.32;
614 table3gpp->m_uLgASD = 1.25;
615 table3gpp->m_sigLgASD = 0.42;
616 table3gpp->m_uLgASA = 1.76;
617 table3gpp->m_sigLgASA = 0.16;
618 table3gpp->m_uLgZSA = 1.01;
619 table3gpp->m_sigLgZSA = 0.43;
620 table3gpp->m_uLgZSD = uLgZSD;
621 table3gpp->m_sigLgZSD = 0.35;
622 table3gpp->m_offsetZOD = offsetZOD;
623 table3gpp->m_cDS = 11e-9;
624 table3gpp->m_cASD = 5;
625 table3gpp->m_cASA = 8;
626 table3gpp->m_cZSA = 3;
628 table3gpp->m_sigK = 0;
629 table3gpp->m_rTau = 2.2;
630 table3gpp->m_uXpr = 9;
631 table3gpp->m_sigXpr = 5;
632 table3gpp->m_perClusterShadowingStd = 4;
634 for (uint8_t row = 0; row < 6; row++)
636 for (uint8_t column = 0; column < 6; column++)
638 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_O2I[row][column];
646 NS_ASSERT_MSG (!o2i,
"The indoor scenario does out support outdoor to indoor");
649 table3gpp->m_numOfCluster = 15;
650 table3gpp->m_raysPerCluster = 20;
651 table3gpp->m_uLgDS = -0.01 * log10 (1 + fcGHz) - 7.692;
652 table3gpp->m_sigLgDS = 0.18;
653 table3gpp->m_uLgASD = 1.60;
654 table3gpp->m_sigLgASD = 0.18;
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;
661 table3gpp->m_offsetZOD = 0;
662 table3gpp->m_cDS = 3.91e-9;
663 table3gpp->m_cASD = 5;
664 table3gpp->m_cASA = 8;
665 table3gpp->m_cZSA = 9;
667 table3gpp->m_sigK = 4;
668 table3gpp->m_rTau = 3.6;
669 table3gpp->m_uXpr = 11;
670 table3gpp->m_sigXpr = 4;
671 table3gpp->m_perClusterShadowingStd = 6;
673 for (uint8_t row = 0; row < 7; row++)
675 for (uint8_t column = 0; column < 7; column++)
683 table3gpp->m_numOfCluster = 19;
684 table3gpp->m_raysPerCluster = 20;
685 table3gpp->m_uLgDS = -0.28 * log10 (1 + fcGHz) - 7.173;
686 table3gpp->m_sigLgDS = 0.1 * log10 (1 + fcGHz) + 0.055;
687 table3gpp->m_uLgASD = 1.62;
688 table3gpp->m_sigLgASD = 0.25;
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;
693 table3gpp->m_uLgZSD = 1.08;
694 table3gpp->m_sigLgZSD = 0.36;
695 table3gpp->m_offsetZOD = 0;
696 table3gpp->m_cDS = 3.91e-9;
697 table3gpp->m_cASD = 5;
698 table3gpp->m_cASA = 11;
699 table3gpp->m_cZSA = 9;
701 table3gpp->m_sigK = 0;
702 table3gpp->m_rTau = 3;
703 table3gpp->m_uXpr = 10;
704 table3gpp->m_sigXpr = 4;
705 table3gpp->m_perClusterShadowingStd = 3;
707 for (uint8_t row = 0; row < 6; row++)
709 for (uint8_t column = 0; column < 6; column++)
718 if (channelCondition->IsLos ())
722 table3gpp->m_numOfCluster = 12;
723 table3gpp->m_raysPerCluster = 20;
724 table3gpp->m_uLgDS = -0.2 * log10 (1 + fcGHz) - 7.5;
725 table3gpp->m_sigLgDS = 0.1;
726 table3gpp->m_uLgASD = -0.1 * log10 (1 + fcGHz) + 1.6;
727 table3gpp->m_sigLgASD = 0.1;
728 table3gpp->m_uLgASA = -0.1 * log10 (1 + fcGHz) + 1.6;
729 table3gpp->m_sigLgASA = 0.1;
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;
734 table3gpp->m_offsetZOD = 0;
735 table3gpp->m_cDS = 5;
736 table3gpp->m_cASD = 17;
737 table3gpp->m_cASA = 17;
738 table3gpp->m_cZSA = 7;
739 table3gpp->m_uK = 3.48;
740 table3gpp->m_sigK = 2;
741 table3gpp->m_rTau = 3;
742 table3gpp->m_uXpr = 9;
743 table3gpp->m_sigXpr = 3;
744 table3gpp->m_perClusterShadowingStd = 4;
746 for (uint8_t row = 0; row < 7; row++)
748 for (uint8_t column = 0; column < 7; column++)
750 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_LOS[row][column];
754 else if (channelCondition->IsNlos ())
756 table3gpp->m_numOfCluster = 19;
757 table3gpp->m_raysPerCluster = 20;
758 table3gpp->m_uLgDS = -0.3 * log10 (1 + fcGHz) - 7;
759 table3gpp->m_sigLgDS = 0.28;
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;
768 table3gpp->m_offsetZOD = 0;
769 table3gpp->m_cDS = 11;
770 table3gpp->m_cASD = 22;
771 table3gpp->m_cASA = 22;
772 table3gpp->m_cZSA = 7;
774 table3gpp->m_sigK = 0;
775 table3gpp->m_rTau = 2.1;
776 table3gpp->m_uXpr = 8;
777 table3gpp->m_sigXpr = 3;
778 table3gpp->m_perClusterShadowingStd = 4;
780 for (uint8_t row = 0; row < 6; row++)
782 for (uint8_t column = 0; column < 6; column++)
788 else if (channelCondition->IsNlosv ())
790 table3gpp->m_numOfCluster = 19;
791 table3gpp->m_raysPerCluster = 20;
792 table3gpp->m_uLgDS = -0.4 * log10 (1 + fcGHz) - 7;
793 table3gpp->m_sigLgDS = 0.1;
794 table3gpp->m_uLgASD = -0.1 * log10 (1 + fcGHz) + 1.7;
795 table3gpp->m_sigLgASD = 0.1;
796 table3gpp->m_uLgASA = -0.1 * log10 (1 + fcGHz) + 1.7;
797 table3gpp->m_sigLgASA = 0.1;
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;
802 table3gpp->m_offsetZOD = 0;
803 table3gpp->m_cDS = 11;
804 table3gpp->m_cASD = 22;
805 table3gpp->m_cASA = 22;
806 table3gpp->m_cZSA = 7;
808 table3gpp->m_sigK = 4.5;
809 table3gpp->m_rTau = 2.1;
810 table3gpp->m_uXpr = 8;
811 table3gpp->m_sigXpr = 3;
812 table3gpp->m_perClusterShadowingStd = 4;
814 for (uint8_t row = 0; row < 6; row++)
816 for (uint8_t column = 0; column < 6; column++)
818 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_LOS[row][column];
829 if (channelCondition->IsLos ())
831 table3gpp->m_numOfCluster = 12;
832 table3gpp->m_raysPerCluster = 20;
833 table3gpp->m_uLgDS = -8.3;
834 table3gpp->m_sigLgDS = 0.2;
835 table3gpp->m_uLgASD = 1.4;
836 table3gpp->m_sigLgASD = 0.1;
837 table3gpp->m_uLgASA = 1.4;
838 table3gpp->m_sigLgASA = 0.1;
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;
843 table3gpp->m_offsetZOD = 0;
844 table3gpp->m_cDS = 5;
845 table3gpp->m_cASD = 17;
846 table3gpp->m_cASA = 17;
847 table3gpp->m_cZSA = 7;
849 table3gpp->m_sigK = 3.5;
850 table3gpp->m_rTau = 3;
851 table3gpp->m_uXpr = 9;
852 table3gpp->m_sigXpr = 3;
853 table3gpp->m_perClusterShadowingStd = 4;
855 for (uint8_t row = 0; row < 7; row++)
857 for (uint8_t column = 0; column < 7; column++)
859 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_LOS[row][column];
863 else if (channelCondition->IsNlosv ())
865 table3gpp->m_numOfCluster = 19;
866 table3gpp->m_raysPerCluster = 20;
867 table3gpp->m_uLgDS = -8.3;
868 table3gpp->m_sigLgDS = 0.3;
869 table3gpp->m_uLgASD = 1.5;
870 table3gpp->m_sigLgASD = 0.1;
871 table3gpp->m_uLgASA = 1.5;
872 table3gpp->m_sigLgASA = 0.1;
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;
877 table3gpp->m_offsetZOD = 0;
878 table3gpp->m_cDS = 11;
879 table3gpp->m_cASD = 22;
880 table3gpp->m_cASA = 22;
881 table3gpp->m_cZSA = 7;
883 table3gpp->m_sigK = 4.5;
884 table3gpp->m_rTau = 2.1;
885 table3gpp->m_uXpr = 8.0;
886 table3gpp->m_sigXpr = 3;
887 table3gpp->m_perClusterShadowingStd = 4;
889 for (uint8_t row = 0; row < 6; row++)
891 for (uint8_t column = 0; column < 6; column++)
893 table3gpp->m_sqrtC[row][column] =
sqrtC_UMi_LOS[row][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");
901 table3gpp->m_numOfCluster = 19;
902 table3gpp->m_raysPerCluster = 20;
903 table3gpp->m_uLgDS = -0.3 * log10 (1 + fcGHz) - 7;
904 table3gpp->m_sigLgDS = 0.28;
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;
913 table3gpp->m_offsetZOD = 0;
914 table3gpp->m_cDS = 11;
915 table3gpp->m_cASD = 22;
916 table3gpp->m_cASA = 22;
917 table3gpp->m_cZSA = 7;
919 table3gpp->m_sigK = 0;
920 table3gpp->m_rTau = 2.1;
921 table3gpp->m_uXpr = 8;
922 table3gpp->m_sigXpr = 3;
923 table3gpp->m_perClusterShadowingStd = 4;
925 for (uint8_t row = 0; row < 6; row++)
927 for (uint8_t column = 0; column < 6; column++)
954 if (!channelMatrix->m_channelCondition->IsEqual (channelCondition))
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
1054 uint8_t numOfCluster = table3gpp->m_numOfCluster;
1055 uint8_t raysPerCluster = table3gpp->m_raysPerCluster;
1059 channelParams->m_channelCondition = channelCondition;
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;
1100 DS = pow (10, LSPs[2] * table3gpp->m_sigLgDS + table3gpp->m_uLgDS);
1101 ASD = pow (10, LSPs[3] * table3gpp->m_sigLgASD + table3gpp->m_uLgASD);
1102 ASA = pow (10, LSPs[4] * table3gpp->m_sigLgASA + table3gpp->m_uLgASA);
1103 ZSD = pow (10, LSPs[5] * table3gpp->m_sigLgZSD + table3gpp->m_uLgZSD);
1104 ZSA = pow (10, LSPs[6] * table3gpp->m_sigLgZSA + table3gpp->m_uLgZSA);
1108 DS = pow (10, LSPs[1] * table3gpp->m_sigLgDS + table3gpp->m_uLgDS);
1109 ASD = pow (10, LSPs[2] * table3gpp->m_sigLgASD + table3gpp->m_uLgASD);
1110 ASA = pow (10, LSPs[3] * table3gpp->m_sigLgASA + table3gpp->m_uLgASA);
1111 ZSD = pow (10, LSPs[4] * table3gpp->m_sigLgZSD + table3gpp->m_uLgZSD);
1112 ZSA = pow (10, LSPs[5] * table3gpp->m_sigLgZSA + table3gpp->m_uLgZSA);
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) *
1153 pow (10,-1 *
m_normalRv->GetValue () * table3gpp->m_perClusterShadowingStd / 10);
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 ();
1213 channelParams->m_numCluster = numReducedCluster;
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++)
1378 double tempAoa = clusterAoa[nInd] + table3gpp->m_cASA *
offSetAlpha[mInd];
1379 double tempZoa = clusterZoa[nInd] + table3gpp->m_cZSA *
offSetAlpha[mInd];
1382 double tempAod = clusterAod[nInd] + table3gpp->m_cASD *
offSetAlpha[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);
1496 channelParams->m_clusterPhase = clusterPhase;
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 () <<
"]");
1750 channelParams->m_channel = H_usn;
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)
double f(double x, void *params)
Class holding the azimuth and inclination angles of spherical coordinates.
double GetInclination(void) const
Getter for inclination angle.
double GetAzimuth(void) const
Getter for azimuth angle.
AttributeValue implementation for Boolean.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Hold a signed integer type.
This is an interface for a channel model that can be described by a channel matrix,...
std::vector< Complex2DVector > Complex3DVector
type definition for complex 3D matrices
std::vector< DoubleVector > Double2DVector
type definition for matrices of doubles
static constexpr uint32_t GetKey(uint32_t x1, uint32_t x2)
Calculate the channel key using the Cantor function.
std::vector< double > DoubleVector
type definition for vectors of doubles
std::vector< Double2DVector > Double3DVector
type definition for 3D matrices of doubles
uint32_t GetId(void) const
A base class which provides memory management and object aggregation.
Hold objects of type Ptr<T>.
Smart pointer class similar to boost::intrusive_ptr.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static Time Now(void)
Return the current simulation virtual time.
Hold variables of type string.
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
virtual Ptr< const ParamsTable > GetThreeGppTable(Ptr< const ChannelCondition > channelCondition, double hBS, double hUT, double distance2D) const
Get the parameters needed to apply the channel generation procedure.
Ptr< NormalRandomVariable > m_normalRv
normal random variable
static const uint8_t Y_INDEX
index of the Y value in the m_nonSelfBlocking array
bool m_blockage
enables the blockage model A
~ThreeGppChannelModel()
Destructor.
static const uint8_t THETA_INDEX
index of the THETA value in the m_nonSelfBlocking array
static std::pair< double, double > WrapAngles(double azimuthRad, double inclinationRad)
Wrap an (azimuth, inclination) angle pair in a valid range.
ThreeGppChannelModel()
Constructor.
double m_blockerSpeed
the blocker speed
Ptr< const ChannelMatrix > GetChannel(Ptr< const MobilityModel > aMob, Ptr< const MobilityModel > bMob, Ptr< const PhasedArrayModel > aAntenna, Ptr< const PhasedArrayModel > bAntenna) override
Looks for the channel matrix associated to the aMob and bMob pair in m_channelMap.
void SetFrequency(double f)
Sets the center frequency of the model.
Ptr< UniformRandomVariable > m_uniformRv
uniform random variable
void DoDispose() override
Destructor implementation.
void SetScenario(const std::string &scenario)
Sets the propagation scenario.
void SetChannelConditionModel(Ptr< ChannelConditionModel > model)
Set the channel condition model.
uint16_t m_numNonSelfBlocking
number of non-self-blocking regions
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....
static const uint8_t PHI_INDEX
index of the PHI value in the m_nonSelfBlocking array
double m_frequency
the operating frequency
Ptr< ChannelConditionModel > GetChannelConditionModel() const
Get the associated channel condition model.
Ptr< ChannelConditionModel > m_channelConditionModel
the channel condition model
std::string m_scenario
the 3GPP scenario
std::string GetScenario(void) const
Returns the propagation scenario.
static const uint8_t R_INDEX
index of the R value in the m_nonSelfBlocking array
double GetFrequency(void) const
Returns the center frequency.
static TypeId GetTypeId()
Get the type ID.
std::unordered_map< uint32_t, Ptr< ThreeGppChannelMatrix > > m_channelMap
map containing the channel realizations
DoubleVector CalcAttenuationOfBlockage(Ptr< ThreeGppChannelMatrix > params, const DoubleVector &clusterAOA, const DoubleVector &clusterZOA) const
Applies the blockage model A described in 3GPP TR 38.901.
bool ChannelMatrixNeedsUpdate(Ptr< const ThreeGppChannelMatrix > channelMatrix, Ptr< const ChannelCondition > channelCondition) const
Check if the channel matrix has to be updated.
void Shuffle(double *first, double *last) const
Shuffle the elements of a simple sequence container of type double.
Time m_updatePeriod
the channel update period
static const uint8_t X_INDEX
index of the X value in the m_nonSelfBlocking array
Ptr< UniformRandomVariable > m_uniformRvShuffle
uniform random variable used to shuffle array in GetNewChannel
bool IsZero(void) const
Exactly equivalent to t == 0.
AttributeValue implementation for Time.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeAccessor > MakeStringAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeChecker > MakeStringChecker(void)
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static const double offSetAlpha[20]
static const double sqrtC_RMa_O2I[6][6]
static const double sqrtC_UMi_LOS[7][7]
static const double sqrtC_office_LOS[7][7]
static const double sqrtC_UMa_O2I[6][6]
double max(double x, double y)
static const double sqrtC_RMa_NLOS[6][6]
double min(double x, double y)
static const double sqrtC_UMa_LOS[7][7]
static const double sqrtC_UMi_NLOS[6][6]
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
static const double sqrtC_RMa_LOS[7][7]
double DegreesToRadians(double degrees)
converts degrees to radians
static const double sqrtC_UMi_O2I[6][6]
static const double sqrtC_office_NLOS[6][6]
static const double sqrtC_UMa_NLOS[6][6]
double WrapTo2Pi(double a)
Wrap angle in [0, 2*M_PI)
double RadiansToDegrees(double radians)
converts radians to degrees