A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
three-gpp-propagation-loss-model.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 SIGNET Lab, Department of Information Engineering,
3 * University of Padova
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 */
7
9
11
12#include "ns3/boolean.h"
13#include "ns3/double.h"
14#include "ns3/geocentric-constant-position-mobility-model.h"
15#include "ns3/log.h"
16#include "ns3/mobility-model.h"
17#include "ns3/node.h"
18#include "ns3/pointer.h"
19#include "ns3/simulator.h"
20
21#include <cmath>
22
23namespace
24{
25/**
26 * The enumerator used for code clarity when performing parameter assignment in the GetLoss Methods
27 */
37
38/**
39 * The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the
40 * NTN Dense Urban scenario
41 */
42const std::map<int, std::vector<float>> SFCL_DenseUrban{
43 {10, {3.5, 15.5, 34.3, 2.9, 17.1, 44.3}},
44 {20, {3.4, 13.9, 30.9, 2.4, 17.1, 39.9}},
45 {30, {2.9, 12.4, 29.0, 2.7, 15.6, 37.5}},
46 {40, {3.0, 11.7, 27.7, 2.4, 14.6, 35.8}},
47 {50, {3.1, 10.6, 26.8, 2.4, 14.2, 34.6}},
48 {60, {2.7, 10.5, 26.2, 2.7, 12.6, 33.8}},
49 {70, {2.5, 10.1, 25.8, 2.6, 12.1, 33.3}},
50 {80, {2.3, 9.2, 25.5, 2.8, 12.3, 33.0}},
51 {90, {1.2, 9.2, 25.5, 0.6, 12.3, 32.9}},
52};
53
54/**
55 * The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the
56 * NTN Urban scenario
57 */
58const std::map<int, std::vector<float>> SFCL_Urban{
59 {10, {4, 6, 34.3, 4, 6, 44.3}},
60 {20, {4, 6, 30.9, 4, 6, 39.9}},
61 {30, {4, 6, 29.0, 4, 6, 37.5}},
62 {40, {4, 6, 27.7, 4, 6, 35.8}},
63 {50, {4, 6, 26.8, 4, 6, 34.6}},
64 {60, {4, 6, 26.2, 4, 6, 33.8}},
65 {70, {4, 6, 25.8, 4, 6, 33.3}},
66 {80, {4, 6, 25.5, 4, 6, 33.0}},
67 {90, {4, 6, 25.5, 4, 6, 32.9}},
68};
69
70/**
71 * The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the
72 * NTN Suburban and Rural scenarios
73 */
74const std::map<int, std::vector<float>> SFCL_SuburbanRural{
75 {10, {1.79, 8.93, 19.52, 1.9, 10.7, 29.5}},
76 {20, {1.14, 9.08, 18.17, 1.6, 10.0, 24.6}},
77 {30, {1.14, 8.78, 18.42, 1.9, 11.2, 21.9}},
78 {40, {0.92, 10.25, 18.28, 2.3, 11.6, 20.0}},
79 {50, {1.42, 10.56, 18.63, 2.7, 11.8, 18.7}},
80 {60, {1.56, 10.74, 17.68, 3.1, 10.8, 17.8}},
81 {70, {0.85, 10.17, 16.5, 3.0, 10.8, 17.2}},
82 {80, {0.72, 11.52, 16.3, 3.6, 10.8, 16.9}},
83 {90, {0.72, 11.52, 16.3, 0.4, 10.8, 16.8}},
84};
85
86/**
87 * Array containing the attenuation given by atmospheric absorption. 100 samples are selected for
88 * frequencies from 1GHz to 100GHz. In order to get the atmospheric absorption loss for a given
89 * frequency f: 1- round f to the closest integer between 0 and 100. 2- use the obtained integer to
90 * access the corresponding element in the array, that will give the attenuation at that frequency.
91 * Data is obtained form ITU-R P.676 Figure 6.
92 */
93const double atmosphericAbsorption[101] = {
94 0, 0.0300, 0.0350, 0.0380, 0.0390, 0.0410, 0.0420, 0.0450, 0.0480, 0.0500,
95 0.0530, 0.0587, 0.0674, 0.0789, 0.0935, 0.1113, 0.1322, 0.1565, 0.1841, 0.2153,
96 0.2500, 0.3362, 0.4581, 0.5200, 0.5200, 0.5000, 0.4500, 0.3850, 0.3200, 0.2700,
97 0.2500, 0.2517, 0.2568, 0.2651, 0.2765, 0.2907, 0.3077, 0.3273, 0.3493, 0.3736,
98 0.4000, 0.4375, 0.4966, 0.5795, 0.6881, 0.8247, 0.9912, 1.1900, 1.4229, 1.6922,
99 2.0000, 4.2654, 10.1504, 19.2717, 31.2457, 45.6890, 62.2182, 80.4496, 100.0000, 140.0205,
100 170.0000, 100.0000, 78.1682, 59.3955, 43.5434, 30.4733, 20.0465, 12.1244, 6.5683, 3.2397,
101 2.0000, 1.7708, 1.5660, 1.3858, 1.2298, 1.0981, 0.9905, 0.9070, 0.8475, 0.8119,
102 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000,
103 0.8000, 0.8029, 0.8112, 0.8243, 0.8416, 0.8625, 0.8864, 0.9127, 0.9408, 0.9701,
104 1.0000};
105
106/**
107 * Map containing the Tropospheric attenuation in dB with 99% probability at 20 GHz in Toulouse
108 * used for tropospheric scintillation losses. From Table 6.6.6.2.1-1 of 3GPP TR 38.811.
109 */
110const std::map<int, float> troposphericScintillationLoss{
111 {10, {1.08}},
112 {20, {0.48}},
113 {30, {0.30}},
114 {40, {0.22}},
115 {50, {0.17}},
116 {60, {0.13}},
117 {70, {0.12}},
118 {80, {0.12}},
119 {90, {0.12}},
120};
121
122/**
123 * @brief Get the base station and user terminal relative distances and heights
124 *
125 * @param a the mobility model of terminal a
126 * @param b the mobility model of terminal b
127 *
128 * @return The tuple [dist2D, dist3D, hBs, hUt], where dist2D and dist3D
129 * are the 2D and 3D distances between a and b, respectively, hBs is the bigger
130 * height and hUt the smallest.
131 */
132std::tuple<double, double, double, double>
135{
136 auto aPos = a->GetPosition();
137 auto bPos = b->GetPosition();
138 double distance2D = ns3::ThreeGppChannelConditionModel::Calculate2dDistance(aPos, bPos);
139 double distance3D = ns3::CalculateDistance(aPos, bPos);
140 double hBs = std::max(aPos.z, bPos.z);
141 double hUt = std::min(aPos.z, bPos.z);
142 return std::make_tuple(distance2D, distance3D, hBs, hUt);
143}
144
145/**
146 * @brief Get the base station and user terminal heights for the UmiStreetCanyon scenario
147 *
148 * @param heightA the first height in meters
149 * @param heightB the second height in meters
150 *
151 * @return The tuple [hBs, hUt], where hBs is assumed to be = 10 and hUt other height.
152 */
153std::tuple<double, double>
154GetBsUtHeightsUmiStreetCanyon(double heightA, double heightB)
155{
156 double hBs = (heightA == 10) ? heightA : heightB;
157 double hUt = (heightA == 10) ? heightB : heightA;
158 return std::make_tuple(hBs, hUt);
159}
160
161/**
162 * @brief Computes the free-space path loss using the formula described in 3GPP TR 38.811,
163 * Table 6.6.2
164 *
165 * @param freq the operating frequency
166 * @param dist3d the 3D distance between the communicating nodes
167 *
168 * @return the path loss for NTN scenarios
169 */
170double
171ComputeNtnPathloss(double freq, double dist3d)
172{
173 return 32.45 + 20 * log10(freq / 1e9) + 20 * log10(dist3d);
174}
175
176/**
177 * @brief Computes the atmospheric absorption loss using the formula described in 3GPP TR 38.811,
178 * Sec 6.6.4
179 *
180 * @param freq the operating frequency
181 * @param elevAngle the elevation angle between the communicating nodes
182 *
183 * @return the atmospheric absorption loss for NTN scenarios
184 */
185double
186ComputeAtmosphericAbsorptionLoss(double freq, double elevAngle)
187{
188 double loss = 0;
189 if ((elevAngle < 10 && freq > 1e9) || freq >= 10e9)
190 {
191 int roundedFreq = round(freq / 10e8);
192 loss += atmosphericAbsorption[roundedFreq] / sin(elevAngle * (M_PI / 180));
193 }
194
195 return loss;
196}
197
198/**
199 * @brief Computes the ionospheric plus tropospheric scintillation loss using the formulas
200 * described in 3GPP TR 38.811, Sec 6.6.6.1-4 and 6.6.6.2, respectively.
201 *
202 * @param freq the operating frequency
203 * @param elevAngleQuantized the quantized elevation angle between the communicating nodes
204 *
205 * @return the ionospheric plus tropospheric scintillation loss for NTN scenarios
206 */
207double
208ComputeIonosphericPlusTroposphericScintillationLoss(double freq, double elevAngleQuantized)
209{
210 double loss = 0;
211 if (freq < 6e9)
212 {
213 // Ionospheric
214 loss = 6.22 / (pow(freq / 1e9, 1.5));
215 }
216 else
217 {
218 // Tropospheric
219 loss = troposphericScintillationLoss.at(elevAngleQuantized);
220 }
221 return loss;
222}
223
224/**
225 * @brief Computes the clutter loss using the formula
226 * described in 3GPP TR 38.811, Sec 6.6.6.1-4 and 6.6.6.2, respectively.
227 *
228 * @param freq the operating frequency
229 * @param elevAngleQuantized the quantized elevation angle between the communicating nodes
230 * @param sfcl the nested map containing the Shadow Fading and
231 * Clutter Loss values for the NTN Suburban and Rural scenario
232 *
233 * @return the clutter loss for NTN scenarios
234 */
235double
237 const std::map<int, std::vector<float>>* sfcl,
238 double elevAngleQuantized)
239{
240 double loss = 0;
241 if (freq < 13.0e9)
242 {
243 loss += (*sfcl).at(elevAngleQuantized)[SFCL_params::S_NLOS_CL]; // Get the Clutter Loss for
244 // the S Band
245 }
246 else
247 {
248 loss += (*sfcl).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_CL]; // Get the Clutter Loss for
249 // the Ka Band
250 }
251
252 return loss;
253}
254
255constexpr double M_C = 3.0e8; //!< propagation velocity in free space
256
257} // namespace
258
259namespace ns3
260{
261
262NS_LOG_COMPONENT_DEFINE("ThreeGppPropagationLossModel");
263
264NS_OBJECT_ENSURE_REGISTERED(ThreeGppPropagationLossModel);
265
266TypeId
268{
269 static TypeId tid =
270 TypeId("ns3::ThreeGppPropagationLossModel")
272 .SetGroupName("Propagation")
273 .AddAttribute("Frequency",
274 "The centre frequency in Hz.",
275 DoubleValue(500.0e6),
279 .AddAttribute("ShadowingEnabled",
280 "Enable/disable shadowing.",
281 BooleanValue(true),
284 .AddAttribute(
285 "ChannelConditionModel",
286 "Pointer to the channel condition model.",
287 PointerValue(),
291 .AddAttribute("EnforceParameterRanges",
292 "Whether to strictly enforce TR38.901 applicability ranges",
293 BooleanValue(false),
296 .AddAttribute(
297 "BuildingPenetrationLossesEnabled",
298 "Enable/disable Building Penetration Losses.",
299 BooleanValue(true),
302 .AddAttribute("MeanVehicularLoss",
303 "9dB for standard cars, 20dB for cars with "
304 "metal coated glass panels.",
305 DoubleValue(9),
308 return tid;
309}
310
336
341
342void
349
350void
356
363
364void
366{
367 NS_LOG_FUNCTION(this);
368 NS_ASSERT_MSG(f >= 500.0e6 && f <= 100.0e9,
369 "Frequency should be between 0.5 and 100 GHz but is " << f);
370 m_frequency = f;
371}
372
373double
379
380bool
385
386double
389 Ptr<MobilityModel> b) const
390{
391 NS_LOG_FUNCTION(this);
392
393 // check if the model is initialized
394 NS_ASSERT_MSG(m_frequency != 0.0, "First set the centre frequency");
395
396 // retrieve the channel condition
397 NS_ASSERT_MSG(m_channelConditionModel, "First set the channel condition model");
398 Ptr<ChannelCondition> cond = m_channelConditionModel->GetChannelCondition(a, b);
399
400 double rxPow = txPowerDbm;
401 rxPow -= GetLoss(cond, a, b);
402
404 {
405 rxPow -= GetShadowing(a, b, cond->GetLosCondition());
406 }
407
408 // get o2i losses
410 ((cond->GetO2iCondition() == ChannelCondition::O2iConditionValue::O2I) ||
411 (cond->GetO2iCondition() == ChannelCondition::O2iConditionValue::I2I &&
412 cond->GetLosCondition() == ChannelCondition::LosConditionValue::NLOS)))
413 {
414 if (m_frequency < 6e9)
415 {
416 // TR 38.901 has a backward compatibility O2I penetration loss for sub 6GHz channels
417 rxPow -= GetO2iSub6GhzPenetrationLoss(a, b, cond->GetLosCondition());
418 }
419 else
420 {
421 if (IsO2iLowPenetrationLoss(cond))
422 {
423 rxPow -= GetO2iLowPenetrationLoss(a, b, cond->GetLosCondition());
424 }
425 else
426 {
427 rxPow -= GetO2iHighPenetrationLoss(a, b, cond->GetLosCondition());
428 }
429 }
430 }
431
432 rxPow -= GetO2iVehicularLoss(a, b, cond->GetO2iCondition());
433
434 return rxPow;
435}
436
437double
440 Ptr<MobilityModel> b) const
441{
442 NS_LOG_FUNCTION(this);
443
444 double loss = 0;
445 switch (cond->GetLosCondition())
446 {
448 loss = GetLossLos(a, b);
449 break;
451 loss = GetLossNlosv(a, b);
452 break;
454 loss = GetLossNlos(a, b);
455 break;
456 default:
457 NS_FATAL_ERROR("Unknown channel condition");
458 }
459
460 return loss;
461}
462
463double
468{
469 NS_LOG_FUNCTION(this);
470
471 double o2iLossValue = 0;
472 double lossTw = 0;
473 double lossIn = 0;
474 double lossNormalVariate = 0;
475
476 // compute the channel key
477 uint32_t key = GetKey(a, b);
478
479 bool notFound = false; // indicates if the o2iLoss value has not been computed yet
480 bool newCondition = false; // indicates if the channel condition has changed
481
482 auto it = m_o2iLossMap.end(); // the o2iLoss map iterator
483 if (m_o2iLossMap.find(key) != m_o2iLossMap.end())
484 {
485 // found the o2iLoss value in the map
486 it = m_o2iLossMap.find(key);
487 newCondition = (it->second.m_condition != cond); // true if the condition changed
488 }
489 else
490 {
491 notFound = true;
492 // add a new entry in the map and update the iterator
493 O2iLossMapItem newItem;
494 it = m_o2iLossMap.insert(it, std::make_pair(key, newItem));
495 }
496
497 if (notFound || newCondition)
498 {
499 // distance2dIn is a single, link-specific, uniformly distributed variable
500 // between 0 and 25 m for UMa and UMi-Street Canyon.
501 double distance2dIn = GetO2iDistance2dInSub6Ghz();
502
503 // calculate penetration losses, see TR 38.901 Table 7.4.3-3
504 lossTw = 20;
505
506 // calculate indoor loss
507 lossIn = 0.5 * distance2dIn;
508
509 // calculate low loss standard deviation
510 lossNormalVariate = 0;
511
512 o2iLossValue = lossTw + lossIn + lossNormalVariate;
513
514 // update the entry in the map
515 it->second.m_o2iLoss = o2iLossValue;
516 it->second.m_condition = cond;
517 }
518 else
519 {
520 o2iLossValue = it->second.m_o2iLoss;
521 }
522
523 return o2iLossValue;
524}
525
526double
531{
532 NS_LOG_FUNCTION(this);
533
534 double o2iLossValue = 0;
535 double lowLossTw = 0;
536 double lossIn = 0;
537 double lowlossNormalVariate = 0;
538 double lGlass = 0;
539 double lConcrete = 0;
540
541 // compute the channel key
542 uint32_t key = GetKey(a, b);
543
544 bool notFound = false; // indicates if the o2iLoss value has not been computed yet
545 bool newCondition = false; // indicates if the channel condition has changed
546
547 auto it = m_o2iLossMap.end(); // the o2iLoss map iterator
548 if (m_o2iLossMap.find(key) != m_o2iLossMap.end())
549 {
550 // found the o2iLoss value in the map
551 it = m_o2iLossMap.find(key);
552 newCondition = (it->second.m_condition != cond); // true if the condition changed
553 }
554 else
555 {
556 notFound = true;
557 // add a new entry in the map and update the iterator
558 O2iLossMapItem newItem;
559 it = m_o2iLossMap.insert(it, std::make_pair(key, newItem));
560 }
561
562 if (notFound || newCondition)
563 {
564 // distance2dIn is minimum of two independently generated uniformly distributed
565 // variables between 0 and 25 m for UMa and UMi-Street Canyon, and between 0 and
566 // 10 m for RMa. 2D−in d shall be UT-specifically generated.
567 double distance2dIn = GetO2iDistance2dIn();
568
569 // calculate material penetration losses, see TR 38.901 Table 7.4.3-1
570 lGlass = 2 + 0.2 * m_frequency / 1e9; // m_frequency is operation frequency in Hz
571 lConcrete = 5 + 4 * m_frequency / 1e9;
572
573 lowLossTw =
574 5 - 10 * log10(0.3 * std::pow(10, -lGlass / 10) + 0.7 * std::pow(10, -lConcrete / 10));
575
576 // calculate indoor loss
577 lossIn = 0.5 * distance2dIn;
578
579 // calculate low loss standard deviation
580 lowlossNormalVariate = m_normalO2iLowLossVar->GetValue();
581
582 o2iLossValue = lowLossTw + lossIn + lowlossNormalVariate;
583
584 // update the entry in the map
585 it->second.m_o2iLoss = o2iLossValue;
586 it->second.m_condition = cond;
587 }
588 else
589 {
590 o2iLossValue = it->second.m_o2iLoss;
591 }
592
593 return o2iLossValue;
594}
595
596double
601{
602 NS_LOG_FUNCTION(this);
603
604 double o2iLossValue = 0;
605 double highLossTw = 0;
606 double lossIn = 0;
607 double highlossNormalVariate = 0;
608 double lIIRGlass = 0;
609 double lConcrete = 0;
610
611 // compute the channel key
612 uint32_t key = GetKey(a, b);
613
614 bool notFound = false; // indicates if the o2iLoss value has not been computed yet
615 bool newCondition = false; // indicates if the channel condition has changed
616
617 auto it = m_o2iLossMap.end(); // the o2iLoss map iterator
618 if (m_o2iLossMap.find(key) != m_o2iLossMap.end())
619 {
620 // found the o2iLoss value in the map
621 it = m_o2iLossMap.find(key);
622 newCondition = (it->second.m_condition != cond); // true if the condition changed
623 }
624 else
625 {
626 notFound = true;
627 // add a new entry in the map and update the iterator
628 O2iLossMapItem newItem;
629 it = m_o2iLossMap.insert(it, std::make_pair(key, newItem));
630 }
631
632 if (notFound || newCondition)
633 {
634 // generate a new independent realization
635
636 // distance2dIn is minimum of two independently generated uniformly distributed
637 // variables between 0 and 25 m for UMa and UMi-Street Canyon, and between 0 and
638 // 10 m for RMa. 2D−in d shall be UT-specifically generated.
639 double distance2dIn = GetO2iDistance2dIn();
640
641 // calculate material penetration losses, see TR 38.901 Table 7.4.3-1
642 lIIRGlass = 23 + 0.3 * m_frequency / 1e9;
643 lConcrete = 5 + 4 * m_frequency / 1e9;
644
645 highLossTw = 5 - 10 * log10(0.7 * std::pow(10, -lIIRGlass / 10) +
646 0.3 * std::pow(10, -lConcrete / 10));
647
648 // calculate indoor loss
649 lossIn = 0.5 * distance2dIn;
650
651 // calculate low loss standard deviation
652 highlossNormalVariate = m_normalO2iHighLossVar->GetValue();
653
654 o2iLossValue = highLossTw + lossIn + highlossNormalVariate;
655
656 // update the entry in the map
657 it->second.m_o2iLoss = o2iLossValue;
658 it->second.m_condition = cond;
659 }
660 else
661 {
662 o2iLossValue = it->second.m_o2iLoss;
663 }
664
665 return o2iLossValue;
666}
667
668bool
670{
671 if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::LOW)
672 {
673 return true;
674 }
675 else if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::HIGH)
676 {
677 return false;
678 }
679 else
680 {
681 NS_ABORT_MSG("If we have set the O2I condition, we shouldn't be here");
682 }
683}
684
685double
687{
688 NS_LOG_FUNCTION(this);
689 NS_FATAL_ERROR("Unsupported channel condition (NLOSv)");
690 return 0;
691}
692
693double
697{
698 NS_LOG_FUNCTION(this);
699
700 double shadowingValue;
701
702 // compute the channel key
703 uint32_t key = GetKey(a, b);
704
705 bool notFound = false; // indicates if the shadowing value has not been computed yet
706 bool newCondition = false; // indicates if the channel condition has changed
707 Vector newDistance; // the distance vector, that is not a distance but a difference
708 auto it = m_shadowingMap.end(); // the shadowing map iterator
709 if (m_shadowingMap.find(key) != m_shadowingMap.end())
710 {
711 // found the shadowing value in the map
712 it = m_shadowingMap.find(key);
713 newDistance = GetVectorDifference(a, b);
714 newCondition = (it->second.m_condition != cond); // true if the condition changed
715 }
716 else
717 {
718 notFound = true;
719
720 // add a new entry in the map and update the iterator
721 ShadowingMapItem newItem;
722 it = m_shadowingMap.insert(it, std::make_pair(key, newItem));
723 }
724
725 if (notFound || newCondition)
726 {
727 // generate a new independent realization
728 shadowingValue = m_normRandomVariable->GetValue() * GetShadowingStd(a, b, cond);
729 }
730 else
731 {
732 // compute a new correlated shadowing loss
733 Vector2D displacement(newDistance.x - it->second.m_distance.x,
734 newDistance.y - it->second.m_distance.y);
735 double R = exp(-1 * displacement.GetLength() / GetShadowingCorrelationDistance(cond));
736 shadowingValue = R * it->second.m_shadowing + sqrt(1 - R * R) *
737 m_normRandomVariable->GetValue() *
738 GetShadowingStd(a, b, cond);
739 }
740
741 // update the entry in the map
742 it->second.m_shadowing = shadowingValue;
743 it->second.m_distance = newDistance; // Save the (0,0,0) vector in case it's the first time we
744 // are calculating this value
745 it->second.m_condition = cond;
746
747 return shadowingValue;
748}
749
750int64_t
752{
753 NS_LOG_FUNCTION(this);
754
755 m_normRandomVariable->SetStream(stream);
756 m_randomO2iVar1->SetStream(stream + 1);
757 m_randomO2iVar2->SetStream(stream + 2);
758 m_normalO2iLowLossVar->SetStream(stream + 3);
759 m_normalO2iHighLossVar->SetStream(stream + 4);
760 m_normalO2iVehicularLossVar->SetStream(stream + 5);
761 return 5;
762}
763
764double
766{
767 double x = a.x - b.x;
768 double y = a.y - b.y;
769 double distance2D = sqrt(x * x + y * y);
770
771 return distance2D;
772}
773
776{
777 // use the nodes ids to obtain an unique key for the channel between a and b
778 // sort the nodes ids so that the key is reciprocal
779 uint32_t x1 = std::min(a->GetObject<Node>()->GetId(), b->GetObject<Node>()->GetId());
780 uint32_t x2 = std::max(a->GetObject<Node>()->GetId(), b->GetObject<Node>()->GetId());
781
782 // use the cantor function to obtain the key
783 uint32_t key = (((x1 + x2) * (x1 + x2 + 1)) / 2) + x2;
784
785 return key;
786}
787
788Vector
790{
791 uint32_t x1 = a->GetObject<Node>()->GetId();
792 uint32_t x2 = b->GetObject<Node>()->GetId();
793
794 if (x1 < x2)
795 {
796 return b->GetPosition() - a->GetPosition();
797 }
798 else
799 {
800 return a->GetPosition() - b->GetPosition();
801 }
802}
803
804double
809
810void
817
818double
822{
823 NS_LOG_FUNCTION(this);
824 double o2iVehicularLoss = 0.0;
825
826 // O2I penetration loss for vehicles only applies between 600 MHz and 60 GHz.
827 if (m_frequency >= 0.6e9 && m_frequency < 60e9)
828 {
829 for (const auto& mob : {a, b})
830 {
831 auto velocityKmH = mob->GetVelocity().GetLength() * 3.6;
832 auto idNode = mob->GetObject<Node>()->GetId();
833 // Slow nodes are considered as pedestrians (no loss)
834 if (velocityKmH < 30)
835 {
836 m_o2iVehicularUtLossMap[idNode] = 0.0;
837 }
838 // Fast nodes are considered vehicles.
839 // Create one loss per terminal, and reuse throughout simulation.
840 else if (velocityKmH >= 30 && velocityKmH <= 120)
841 {
842 if (m_o2iVehicularUtLossMap.find(idNode) == m_o2iVehicularUtLossMap.end())
843 {
845 }
846 }
847 // Very fast nodes are not modeled
848 else
849 {
851 "O2I loss for high-speed (>120 km/h) transit and satellites not implemented");
852 }
853
854 // Sum vehicle individual losses
856 {
857 o2iVehicularLoss += m_o2iVehicularUtLossMap.at(idNode);
858 }
859 }
860 }
861 return o2iVehicularLoss;
862}
863
864// ------------------------------------------------------------------------- //
865
867
868TypeId
870{
871 static TypeId tid = TypeId("ns3::ThreeGppRmaPropagationLossModel")
873 .SetGroupName("Propagation")
874 .AddConstructor<ThreeGppRmaPropagationLossModel>()
875 .AddAttribute("AvgBuildingHeight",
876 "The average building height in meters.",
877 DoubleValue(5.0),
879 MakeDoubleChecker<double>(5.0, 50.0))
880 .AddAttribute("AvgStreetWidth",
881 "The average street width in meters.",
882 DoubleValue(20.0),
884 MakeDoubleChecker<double>(5.0, 50.0));
885 return tid;
886}
887
896
901
902double
904{
905 // distance2dIn is minimum of two independently generated uniformly distributed variables
906 // between 0 and 10 m for RMa. 2D−in d shall be UT-specifically generated.
907 return std::min(m_randomO2iVar1->GetValue(0, 10), m_randomO2iVar2->GetValue(0, 10));
908}
909
910bool
912 [[maybe_unused]]) const
913{
914 // Based on 3GPP 38.901 7.4.3.1 in RMa only low losses are applied.
915 // Therefore enforce low losses.
916 return true;
917}
918
919double
921{
922 NS_LOG_FUNCTION(this);
923 NS_ASSERT_MSG(m_frequency <= 30.0e9,
924 "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
925
926 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
927
928 // check if hBS and hUT are within the specified validity range
929 if (hUt < 1.0 || hUt > 10.0)
930 {
931 NS_ABORT_MSG_IF(m_enforceRanges, "Rma UT height out of range");
933 "The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
934 }
935
936 if (hBs < 10.0 || hBs > 150.0)
937 {
938 NS_ABORT_MSG_IF(m_enforceRanges, "Rma BS height out of range");
940 "The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
941 }
942
943 // NOTE The model is intended to be used for BS-UT links, however we may need to
944 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
945 // interference. In order to apply the model, we need to retrieve the values of
946 // hBS and hUT, but in these cases one of the two falls outside the validity
947 // range and the warning message is printed (hBS for the UT-UT case and hUT
948 // for the BS-BS case).
949
950 double distanceBp = GetBpDistance(m_frequency, hBs, hUt);
951 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
953 distanceBp > 0,
954 "Breakpoint distance is zero (divide-by-zero below); are either hBs or hUt = 0?");
955
956 // check if the distance is outside the validity range
957 if (distance2D < 10.0 || distance2D > 10.0e3)
958 {
959 NS_ABORT_MSG_IF(m_enforceRanges, "Rma distance2D out of range");
960 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
961 "accurate");
962 }
963
964 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
965 double loss = 0;
966 if (distance2D <= distanceBp)
967 {
968 // use PL1
969 loss = Pl1(m_frequency, distance3D, m_h, m_w);
970 }
971 else
972 {
973 // use PL2
974 loss = Pl1(m_frequency, distanceBp, m_h, m_w) + 40 * log10(distance3D / distanceBp);
975 }
976
977 NS_LOG_DEBUG("Loss " << loss);
978
979 return loss;
980}
981
982double
984{
985 NS_LOG_FUNCTION(this);
986 NS_ASSERT_MSG(m_frequency <= 30.0e9,
987 "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
988
989 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
990
991 // check if hBs and hUt are within the validity range
992 if (hUt < 1.0 || hUt > 10.0)
993 {
994 NS_ABORT_MSG_IF(m_enforceRanges, "Rma UT height out of range");
996 "The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
997 }
998
999 if (hBs < 10.0 || hBs > 150.0)
1000 {
1001 NS_ABORT_MSG_IF(m_enforceRanges, "Rma BS height out of range");
1003 "The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
1004 }
1005
1006 // NOTE The model is intended to be used for BS-UT links, however we may need to
1007 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1008 // interference. In order to apply the model, we need to retrieve the values of
1009 // hBS and hUT, but in these cases one of the two falls outside the validity
1010 // range and the warning message is printed (hBS for the UT-UT case and hUT
1011 // for the BS-BS case).
1012
1013 // check if the distance is outside the validity range
1014 if (distance2D < 10.0 || distance2D > 5.0e3)
1015 {
1016 NS_ABORT_MSG_IF(m_enforceRanges, "distance2D out of range");
1017 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1018 "accurate");
1019 }
1020
1021 // compute the pathloss
1022 double plNlos = 161.04 - 7.1 * log10(m_w) + 7.5 * log10(m_h) -
1023 (24.37 - 3.7 * pow((m_h / hBs), 2)) * log10(hBs) +
1024 (43.42 - 3.1 * log10(hBs)) * (log10(distance3D) - 3.0) +
1025 20.0 * log10(m_frequency / 1e9) - (3.2 * pow(log10(11.75 * hUt), 2) - 4.97);
1026
1027 double loss = std::max(GetLossLos(a, b), plNlos);
1028
1029 NS_LOG_DEBUG("Loss " << loss);
1030
1031 return loss;
1032}
1033
1034double
1038{
1039 NS_LOG_FUNCTION(this);
1040 double shadowingStd;
1041
1043 {
1044 // compute the 2D distance between the two nodes
1045 double distance2d = Calculate2dDistance(a->GetPosition(), b->GetPosition());
1046
1047 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 5)
1048 double distanceBp = GetBpDistance(m_frequency, a->GetPosition().z, b->GetPosition().z);
1049
1050 if (distance2d <= distanceBp)
1051 {
1052 shadowingStd = 4.0;
1053 }
1054 else
1055 {
1056 shadowingStd = 6.0;
1057 }
1058 }
1060 {
1061 shadowingStd = 8.0;
1062 }
1063 else
1064 {
1065 NS_FATAL_ERROR("Unknown channel condition");
1066 }
1067
1068 return shadowingStd;
1069}
1070
1071double
1074{
1075 NS_LOG_FUNCTION(this);
1076 double correlationDistance;
1077
1078 // See 3GPP TR 38.901, Table 7.5-6
1080 {
1081 correlationDistance = 37;
1082 }
1084 {
1085 correlationDistance = 120;
1086 }
1087 else
1088 {
1089 NS_FATAL_ERROR("Unknown channel condition");
1090 }
1091
1092 return correlationDistance;
1093}
1094
1095double
1096ThreeGppRmaPropagationLossModel::Pl1(double frequency, double distance3D, double h, double /* w */)
1097{
1098 double loss = 20.0 * log10(40.0 * M_PI * distance3D * frequency / 1e9 / 3.0) +
1099 std::min(0.03 * pow(h, 1.72), 10.0) * log10(distance3D) -
1100 std::min(0.044 * pow(h, 1.72), 14.77) + 0.002 * log10(h) * distance3D;
1101 return loss;
1102}
1103
1104double
1105ThreeGppRmaPropagationLossModel::GetBpDistance(double frequency, double hA, double hB)
1106{
1107 double distanceBp = 2.0 * M_PI * hA * hB * frequency / M_C;
1108 return distanceBp;
1109}
1110
1111// ------------------------------------------------------------------------- //
1112
1114
1115TypeId
1117{
1118 static TypeId tid = TypeId("ns3::ThreeGppUmaPropagationLossModel")
1120 .SetGroupName("Propagation")
1121 .AddConstructor<ThreeGppUmaPropagationLossModel>();
1122 return tid;
1123}
1124
1133
1138
1139double
1140ThreeGppUmaPropagationLossModel::GetBpDistance(double hUt, double hBs, double distance2D) const
1141{
1142 NS_LOG_FUNCTION(this);
1143
1144 // compute g (d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1145 double g = 0.0;
1146 if (distance2D > 18.0)
1147 {
1148 g = 5.0 / 4.0 * pow(distance2D / 100.0, 3) * exp(-distance2D / 150.0);
1149 }
1150
1151 // compute C (hUt, d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1152 double c = 0.0;
1153 if (hUt >= 13.0)
1154 {
1155 c = pow((hUt - 13.0) / 10.0, 1.5) * g;
1156 }
1157
1158 // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1159 double prob = 1.0 / (1.0 + c);
1160 double hE = 0.0;
1161 if (m_uniformVar->GetValue() < prob)
1162 {
1163 hE = 1.0;
1164 }
1165 else
1166 {
1167 int random = m_uniformVar->GetInteger(12, std::max(12, (int)(hUt - 1.5)));
1168 hE = (double)floor(random / 3.0) * 3.0;
1169 }
1170
1171 // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1172 double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
1173
1174 return distanceBp;
1175}
1176
1177double
1179{
1180 NS_LOG_FUNCTION(this);
1181
1182 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
1183
1184 // check if hBS and hUT are within the validity range
1185 if (hUt < 1.5 || hUt > 22.5)
1186 {
1187 NS_ABORT_MSG_IF(m_enforceRanges, "Uma UT height out of range");
1189 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
1190 }
1191
1192 if (hBs != 25.0)
1193 {
1194 NS_ABORT_MSG_IF(m_enforceRanges, "Uma BS height out of range");
1195 NS_LOG_WARN("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
1196 }
1197
1198 // NOTE The model is intended to be used for BS-UT links, however we may need to
1199 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1200 // interference. In order to apply the model, we need to retrieve the values of
1201 // hBS and hUT, but in these cases one of the two falls outside the validity
1202 // range and the warning message is printed (hBS for the UT-UT case and hUT
1203 // for the BS-BS case).
1204
1205 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
1206 double distanceBp = GetBpDistance(hUt, hBs, distance2D);
1207 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
1208
1209 // check if the distance is outside the validity range
1210 if (distance2D < 10.0 || distance2D > 5.0e3)
1211 {
1212 NS_ABORT_MSG_IF(m_enforceRanges, "Uma 2D distance out of range");
1213 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1214 "accurate");
1215 }
1216
1217 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1218 double loss = 0;
1219 if (distance2D <= distanceBp)
1220 {
1221 // use PL1
1222 loss = 28.0 + 22.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1223 }
1224 else
1225 {
1226 // use PL2
1227 loss = 28.0 + 40.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) -
1228 9.0 * log10(pow(distanceBp, 2) + pow(hBs - hUt, 2));
1229 }
1230
1231 NS_LOG_DEBUG("Loss " << loss);
1232
1233 return loss;
1234}
1235
1236double
1238{
1239 // distance2dIn is minimum of two independently generated uniformly distributed variables
1240 // between 0 and 25 m for UMa and UMi-Street Canyon. 2D−in d shall be UT-specifically generated.
1241 return std::min(m_randomO2iVar1->GetValue(0, 25), m_randomO2iVar2->GetValue(0, 25));
1242}
1243
1244double
1246{
1247 // distance2dIn is a single, link-specific, uniformly distributed variable between 0 and 25 m.
1248 return m_randomO2iVar1->GetValue(0, 25);
1249}
1250
1251double
1253{
1254 NS_LOG_FUNCTION(this);
1255
1256 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
1257
1258 // check if hBS and hUT are within the validity range
1259 if (hUt < 1.5 || hUt > 22.5)
1260 {
1261 NS_ABORT_MSG_IF(m_enforceRanges, "Uma UT height out of range");
1263 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
1264 }
1265
1266 if (hBs != 25.0)
1267 {
1268 NS_ABORT_MSG_IF(m_enforceRanges, "Uma BS height out of range");
1269 NS_LOG_WARN("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
1270 }
1271
1272 // NOTE The model is intended to be used for BS-UT links, however we may need to
1273 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1274 // interference. In order to apply the model, we need to retrieve the values of
1275 // hBS and hUT, but in these cases one of the two falls outside the validity
1276 // range and the warning message is printed (hBS for the UT-UT case and hUT
1277 // for the BS-BS case).
1278
1279 // check if the distance is outside the validity range
1280 if (distance2D < 10.0 || distance2D > 5.0e3)
1281 {
1282 NS_ABORT_MSG_IF(m_enforceRanges, "Uma 2D distance out of range");
1283 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1284 "accurate");
1285 }
1286
1287 // compute the pathloss
1288 double plNlos =
1289 13.54 + 39.08 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) - 0.6 * (hUt - 1.5);
1290 double loss = std::max(GetLossLos(a, b), plNlos);
1291 NS_LOG_DEBUG("Loss " << loss);
1292
1293 return loss;
1294}
1295
1296double
1298 Ptr<MobilityModel> /* b */,
1300{
1301 NS_LOG_FUNCTION(this);
1302 double shadowingStd;
1303 if (m_frequency < 6e9)
1304 {
1305 shadowingStd = 7.0;
1306 }
1307 else
1308 {
1310 {
1311 shadowingStd = 4.0;
1312 }
1314 {
1315 shadowingStd = 6.0;
1316 }
1317 else
1318 {
1319 NS_FATAL_ERROR("Unknown channel condition");
1320 }
1321 }
1322 return shadowingStd;
1323}
1324
1325double
1328{
1329 NS_LOG_FUNCTION(this);
1330 double correlationDistance;
1331
1332 // See 3GPP TR 38.901, Table 7.5-6
1334 {
1335 correlationDistance = 37;
1336 }
1338 {
1339 correlationDistance = 50;
1340 }
1341 else
1342 {
1343 NS_FATAL_ERROR("Unknown channel condition");
1344 }
1345
1346 return correlationDistance;
1347}
1348
1349int64_t
1351{
1352 NS_LOG_FUNCTION(this);
1353
1354 m_normRandomVariable->SetStream(stream);
1355 m_uniformVar->SetStream(stream + 1);
1356 return 2;
1357}
1358
1359// ------------------------------------------------------------------------- //
1360
1362
1363TypeId
1365{
1366 static TypeId tid = TypeId("ns3::ThreeGppUmiStreetCanyonPropagationLossModel")
1368 .SetGroupName("Propagation")
1370 return tid;
1371}
1372
1381
1386
1387double
1389 double hBs,
1390 double /* distance2D */) const
1391{
1392 NS_LOG_FUNCTION(this);
1393
1394 // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1395 double hE = 1.0;
1396
1397 // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1398 double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
1399
1400 return distanceBp;
1401}
1402
1403double
1405{
1406 // distance2dIn is minimum of two independently generated uniformly distributed variables
1407 // between 0 and 25 m for UMa and UMi-Street Canyon. 2D−in d shall be UT-specifically generated.
1408 return std::min(m_randomO2iVar1->GetValue(0, 25), m_randomO2iVar2->GetValue(0, 25));
1409}
1410
1411double
1413{
1414 // distance2dIn is a single, link-specific, uniformly distributed variable between 0 and 25 m.
1415 return m_randomO2iVar1->GetValue(0, 25);
1416}
1417
1418double
1420 Ptr<MobilityModel> b) const
1421{
1422 NS_LOG_FUNCTION(this);
1423
1424 double distance2D = Calculate2dDistance(a->GetPosition(), b->GetPosition());
1425 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1426 auto [hBs, hUt] = GetBsUtHeightsUmiStreetCanyon(a->GetPosition().z, b->GetPosition().z);
1427
1428 // check if hBS and hUT are within the validity range
1429 if (hUt < 1.5 || hUt >= 10.0)
1430 {
1431 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon UT height out of range");
1433 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). "
1434 "We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
1435 }
1436
1437 if (hBs != 10.0)
1438 {
1439 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon BS height out of range");
1440 NS_LOG_WARN("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
1441 }
1442
1443 // NOTE The model is intended to be used for BS-UT links, however we may need to
1444 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1445 // interference. In order to apply the model, we need to retrieve the values of
1446 // hBS and hUT, but in these cases one of the two falls outside the validity
1447 // range and the warning message is printed (hBS for the UT-UT case and hUT
1448 // for the BS-BS case).
1449
1450 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
1451 double distanceBp = GetBpDistance(hUt, hBs, distance2D);
1452 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
1453
1454 // check if the distance is outside the validity range
1455 if (distance2D < 10.0 || distance2D > 5.0e3)
1456 {
1457 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon 2D distance out of range");
1458 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1459 "accurate");
1460 }
1461
1462 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1463 double loss = 0;
1464 if (distance2D <= distanceBp)
1465 {
1466 // use PL1
1467 loss = 32.4 + 21.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1468 }
1469 else
1470 {
1471 // use PL2
1472 loss = 32.4 + 40.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) -
1473 9.5 * log10(pow(distanceBp, 2) + pow(hBs - hUt, 2));
1474 }
1475
1476 NS_LOG_DEBUG("Loss " << loss);
1477
1478 return loss;
1479}
1480
1481double
1483 Ptr<MobilityModel> b) const
1484{
1485 NS_LOG_FUNCTION(this);
1486
1487 double distance2D = Calculate2dDistance(a->GetPosition(), b->GetPosition());
1488 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1489 auto [hBs, hUt] = GetBsUtHeightsUmiStreetCanyon(a->GetPosition().z, b->GetPosition().z);
1490
1491 // check if hBS and hUT are within the validity range
1492 if (hUt < 1.5 || hUt >= 10.0)
1493 {
1494 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon UT height out of range");
1496 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). "
1497 "We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
1498 }
1499
1500 if (hBs != 10.0)
1501 {
1502 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon BS height out of range");
1503 NS_LOG_WARN("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
1504 }
1505
1506 // NOTE The model is intended to be used for BS-UT links, however we may need to
1507 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1508 // interference. In order to apply the model, we need to retrieve the values of
1509 // hBS and hUT, but in these cases one of the two falls outside the validity
1510 // range and the warning message is printed (hBS for the UT-UT case and hUT
1511 // for the BS-BS case).
1512
1513 // check if the distance is outside the validity range
1514 if (distance2D < 10.0 || distance2D > 5.0e3)
1515 {
1516 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon 2D distance out of range");
1517 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1518 "accurate");
1519 }
1520
1521 // compute the pathloss
1522 double plNlos =
1523 22.4 + 35.3 * log10(distance3D) + 21.3 * log10(m_frequency / 1e9) - 0.3 * (hUt - 1.5);
1524 double loss = std::max(GetLossLos(a, b), plNlos);
1525 NS_LOG_DEBUG("Loss " << loss);
1526
1527 return loss;
1528}
1529
1530double
1532 Ptr<MobilityModel> /* a */,
1533 Ptr<MobilityModel> /* b */,
1535{
1536 NS_LOG_FUNCTION(this);
1537 double shadowingStd;
1538
1539 if (m_frequency < 6e9)
1540 {
1541 shadowingStd = 7.0;
1542 }
1543 else
1544 {
1546 {
1547 shadowingStd = 4.0;
1548 }
1550 {
1551 shadowingStd = 7.82;
1552 }
1553 else
1554 {
1555 NS_FATAL_ERROR("Unknown channel condition");
1556 }
1557 }
1558 return shadowingStd;
1559}
1560
1561double
1564{
1565 NS_LOG_FUNCTION(this);
1566 double correlationDistance;
1567
1568 // See 3GPP TR 38.901, Table 7.5-6
1570 {
1571 correlationDistance = 10;
1572 }
1574 {
1575 correlationDistance = 13;
1576 }
1577 else
1578 {
1579 NS_FATAL_ERROR("Unknown channel condition");
1580 }
1581
1582 return correlationDistance;
1583}
1584
1585// ------------------------------------------------------------------------- //
1586
1588
1589TypeId
1591{
1592 static TypeId tid = TypeId("ns3::ThreeGppIndoorOfficePropagationLossModel")
1594 .SetGroupName("Propagation")
1596 return tid;
1597}
1598
1607
1612
1613double
1618
1619double
1621 Ptr<MobilityModel> b) const
1622{
1623 NS_LOG_FUNCTION(this);
1624
1625 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1626
1627 // check if the distance is outside the validity range
1628 if (distance3D < 1.0 || distance3D > 150.0)
1629 {
1630 NS_ABORT_MSG_IF(m_enforceRanges, "IndoorOffice 3D distance out of range");
1631 NS_LOG_WARN("The 3D distance is outside the validity range, the pathloss value may not be "
1632 "accurate");
1633 }
1634
1635 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1636 double loss = 32.4 + 17.3 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1637
1638 NS_LOG_DEBUG("Loss " << loss);
1639
1640 return loss;
1641}
1642
1643double
1645 Ptr<MobilityModel> b) const
1646{
1647 NS_LOG_FUNCTION(this);
1648
1649 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1650
1651 // check if the distance is outside the validity range
1652 if (distance3D < 1.0 || distance3D > 150.0)
1653 {
1654 NS_ABORT_MSG_IF(m_enforceRanges, "IndoorOffice 3D distance out of range");
1655 NS_LOG_WARN("The 3D distance is outside the validity range, the pathloss value may not be "
1656 "accurate");
1657 }
1658
1659 // compute the pathloss
1660 double plNlos = 17.3 + 38.3 * log10(distance3D) + 24.9 * log10(m_frequency / 1e9);
1661 double loss = std::max(GetLossLos(a, b), plNlos);
1662
1663 NS_LOG_DEBUG("Loss " << loss);
1664
1665 return loss;
1666}
1667
1668double
1670 Ptr<MobilityModel> /* a */,
1671 Ptr<MobilityModel> /* b */,
1673{
1674 NS_LOG_FUNCTION(this);
1675 double shadowingStd;
1676
1678 {
1679 shadowingStd = 3.0;
1680 }
1682 {
1683 shadowingStd = 8.03;
1684 }
1685 else
1686 {
1687 NS_FATAL_ERROR("Unknown channel condition");
1688 }
1689
1690 return shadowingStd;
1691}
1692
1693double
1696{
1697 NS_LOG_FUNCTION(this);
1698
1699 // See 3GPP TR 38.901, Table 7.5-6
1700 double correlationDistance;
1701
1703 {
1704 correlationDistance = 10;
1705 }
1707 {
1708 correlationDistance = 6;
1709 }
1710 else
1711 {
1712 NS_FATAL_ERROR("Unknown channel condition");
1713 }
1714
1715 return correlationDistance;
1716}
1717
1719
1720TypeId
1722{
1723 static TypeId tid = TypeId("ns3::ThreeGppNTNDenseUrbanPropagationLossModel")
1725 .SetGroupName("Propagation")
1727 return tid;
1728}
1729
1737
1742
1743double
1748
1749double
1751 Ptr<MobilityModel> b) const
1752{
1753 NS_LOG_FUNCTION(this);
1754 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1755 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1756
1757 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1758 auto [elevAngle, elevAngleQuantized] =
1760
1761 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1762 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1763
1764 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1765 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1766
1767 // Apply Ionospheric plus Tropospheric Scintillation Loss
1768 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1769
1770 NS_LOG_DEBUG("Loss " << loss);
1771 return loss;
1772}
1773
1774double
1776 Ptr<MobilityModel> b) const
1777{
1778 NS_LOG_FUNCTION(this);
1779 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1780 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1781
1782 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1783 auto [elevAngle, elevAngleQuantized] =
1785
1786 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1787 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1788
1789 // Apply Clutter Loss
1790 loss += ComputeClutterLoss(m_frequency, m_SFCL_DenseUrban, elevAngleQuantized);
1791
1792 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1793 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1794
1795 // Apply Ionospheric plus Tropospheric Scintillation Loss
1796 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1797
1798 NS_LOG_DEBUG("Loss " << loss);
1799 return loss;
1800}
1801
1802double
1807{
1808 NS_LOG_FUNCTION(this);
1809 double shadowingStd;
1810
1811 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
1812 auto [elevAngle, elevAngleQuantized] =
1814
1815 // Assign Shadowing Standard Deviation according to table 6.6.2-1
1816 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
1817 {
1818 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
1819 }
1820 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
1821 {
1822 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
1823 }
1824 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
1825 {
1826 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
1827 }
1828 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
1829 {
1830 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
1831 }
1832 else
1833 {
1834 NS_FATAL_ERROR("Unknown channel condition");
1835 }
1836
1837 return shadowingStd;
1838}
1839
1840double
1843{
1844 NS_LOG_FUNCTION(this);
1845 double correlationDistance;
1846
1847 // See 3GPP TR 38.811, Table 6.7.2-1a/b and Table 6.7.2-2a/b
1849 {
1850 correlationDistance = 37;
1851 }
1853 {
1854 correlationDistance = 50;
1855 }
1856 else
1857 {
1858 NS_FATAL_ERROR("Unknown channel condition");
1859 }
1860
1861 return correlationDistance;
1862}
1863
1864// ------------------------------------------------------------------------- //
1865
1867
1868TypeId
1870{
1871 static TypeId tid = TypeId("ns3::ThreeGppNTNUrbanPropagationLossModel")
1873 .SetGroupName("Propagation")
1874 .AddConstructor<ThreeGppNTNUrbanPropagationLossModel>();
1875 return tid;
1876}
1877
1885
1890
1891double
1896
1897double
1899{
1900 NS_LOG_FUNCTION(this);
1901 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1902 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1903
1904 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1905 auto [elevAngle, elevAngleQuantized] =
1907
1908 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1909 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1910
1911 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1912 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1913
1914 // Apply Ionospheric plus Tropospheric Scintillation Loss
1915 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1916
1917 NS_LOG_DEBUG("Loss " << loss);
1918 return loss;
1919}
1920
1921double
1923{
1924 NS_LOG_FUNCTION(this);
1925 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1926 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1927
1928 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1929 auto [elevAngle, elevAngleQuantized] =
1931
1932 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1933 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1934
1935 // Apply Clutter Loss
1936 loss += ComputeClutterLoss(m_frequency, m_SFCL_Urban, elevAngleQuantized);
1937
1938 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1939 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1940
1941 // Apply Ionospheric plus Tropospheric Scintillation Loss
1942 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1943
1944 NS_LOG_DEBUG("Loss " << loss);
1945 return loss;
1946}
1947
1948double
1953{
1954 NS_LOG_FUNCTION(this);
1955 double shadowingStd;
1956
1957 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
1958 auto [elevAngle, elevAngleQuantized] =
1960
1961 // Assign Shadowing Standard Deviation according to table 6.6.2-1
1962 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
1963 {
1964 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
1965 }
1966 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
1967 {
1968 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
1969 }
1970 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
1971 {
1972 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
1973 }
1974 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
1975 {
1976 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
1977 }
1978 else
1979 {
1980 NS_FATAL_ERROR("Unknown channel condition");
1981 }
1982
1983 return shadowingStd;
1984}
1985
1986double
1989{
1990 NS_LOG_FUNCTION(this);
1991 double correlationDistance;
1992
1993 // See 3GPP TR 38.811, Table 6.7.2-3a/b and Table 6.7.2-3a/b
1995 {
1996 correlationDistance = 37;
1997 }
1999 {
2000 correlationDistance = 50;
2001 }
2002 else
2003 {
2004 NS_FATAL_ERROR("Unknown channel condition");
2005 }
2006
2007 return correlationDistance;
2008}
2009
2010// ------------------------------------------------------------------------- //
2011
2013
2014TypeId
2016{
2017 static TypeId tid = TypeId("ns3::ThreeGppNTNSuburbanPropagationLossModel")
2019 .SetGroupName("Propagation")
2020 .AddConstructor<ThreeGppNTNSuburbanPropagationLossModel>();
2021 return tid;
2022}
2023
2031
2036
2037double
2042
2043double
2045 Ptr<MobilityModel> b) const
2046{
2047 NS_LOG_FUNCTION(this);
2048 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2049 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2050
2051 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2052 auto [elevAngle, elevAngleQuantized] =
2054
2055 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2056 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2057
2058 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2059 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2060
2061 // Apply Ionospheric plus Tropospheric Scintillation Loss
2062 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2063
2064 NS_LOG_DEBUG("Loss " << loss);
2065
2066 return loss;
2067}
2068
2069double
2071 Ptr<MobilityModel> b) const
2072{
2073 NS_LOG_FUNCTION(this);
2074 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2075 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2076
2077 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2078 auto [elevAngle, elevAngleQuantized] =
2080
2081 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2082 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2083
2084 // Apply Clutter Loss
2085 loss += ComputeClutterLoss(m_frequency, m_SFCL_SuburbanRural, elevAngleQuantized);
2086
2087 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2088 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2089
2090 // Apply Ionospheric plus Tropospheric Scintillation Loss
2091 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2092
2093 NS_LOG_DEBUG("Loss " << loss);
2094 return loss;
2095}
2096
2097double
2102{
2103 NS_LOG_FUNCTION(this);
2104 double shadowingStd;
2105
2106 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
2107 auto [elevAngle, elevAngleQuantized] =
2109
2110 // Assign Shadowing Standard Deviation according to table 6.6.2-1
2111 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
2112 {
2113 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
2114 }
2115 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
2116 {
2117 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
2118 }
2119 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
2120 {
2121 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
2122 }
2123 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
2124 {
2125 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
2126 }
2127 else
2128 {
2129 NS_FATAL_ERROR("Unknown channel condition");
2130 }
2131
2132 return shadowingStd;
2133}
2134
2135double
2138{
2139 NS_LOG_FUNCTION(this);
2140 double correlationDistance;
2141
2142 // See 3GPP TR 38.811, Table 6.7.2-5a/b and Table 6.7.2-6a/b
2144 {
2145 correlationDistance = 37;
2146 }
2148 {
2149 correlationDistance = 50;
2150 }
2151 else
2152 {
2153 NS_FATAL_ERROR("Unknown channel condition");
2154 }
2155
2156 return correlationDistance;
2157}
2158
2159// ------------------------------------------------------------------------- //
2160
2162
2163TypeId
2165{
2166 static TypeId tid = TypeId("ns3::ThreeGppNTNRuralPropagationLossModel")
2168 .SetGroupName("Propagation")
2169 .AddConstructor<ThreeGppNTNRuralPropagationLossModel>();
2170 return tid;
2171}
2172
2180
2185
2186double
2191
2192double
2194{
2195 NS_LOG_FUNCTION(this);
2196 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2197 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2198
2199 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2200 auto [elevAngle, elevAngleQuantized] =
2202
2203 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2204 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2205
2206 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2207 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2208
2209 // Apply Ionospheric plus Tropospheric Scintillation Loss
2210 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2211
2212 NS_LOG_DEBUG("Loss " << loss);
2213 return loss;
2214}
2215
2216double
2218{
2219 NS_LOG_FUNCTION(this);
2220 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2221 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2222
2223 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2224 auto [elevAngle, elevAngleQuantized] =
2226
2227 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2228 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2229
2230 // Apply Clutter Loss
2231 loss += ComputeClutterLoss(m_frequency, m_SFCL_SuburbanRural, elevAngleQuantized);
2232
2233 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2234 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2235
2236 // Apply Ionospheric plus Tropospheric Scintillation Loss
2237 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2238
2239 NS_LOG_DEBUG("Loss " << loss);
2240 return loss;
2241}
2242
2243double
2248{
2249 NS_LOG_FUNCTION(this);
2250 double shadowingStd;
2251
2252 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
2253 auto [elevAngle, elevAngleQuantized] =
2255
2256 // Assign Shadowing Standard Deviation according to table 6.6.2-1
2257 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
2258 {
2259 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
2260 }
2261 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
2262 {
2263 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
2264 }
2265 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
2266 {
2267 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
2268 }
2269 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
2270 {
2271 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
2272 }
2273 else
2274 {
2275 NS_FATAL_ERROR("Unknown channel condition");
2276 }
2277
2278 return shadowingStd;
2279}
2280
2281double
2284{
2285 NS_LOG_FUNCTION(this);
2286 double correlationDistance;
2287
2288 // See 3GPP TR 38.811, Table 6.7.2-7a/b and Table 6.7.2-8a/b
2290 {
2291 correlationDistance = 37;
2292 }
2294 {
2295 correlationDistance = 120;
2296 }
2297 else
2298 {
2299 NS_FATAL_ERROR("Unknown channel condition");
2300 }
2301
2302 return correlationDistance;
2303}
2304
2305} // namespace ns3
cairo_uint64_t x
_cairo_uint_96by64_32x64_divrem:
AttributeValue implementation for Boolean.
Definition boolean.h:26
O2iConditionValue
Possible values for Outdoor to Indoor condition.
@ LOW
Low Penetration Losses.
@ HIGH
High Penetration Losses.
LosConditionValue
Possible values for Line-of-Sight condition.
@ NLOSv
Non Line of Sight due to a vehicle.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
A network Node.
Definition node.h:46
uint32_t GetId() const
Definition node.cc:106
AttributeValue implementation for Pointer.
Definition pointer.h:37
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
static double Calculate2dDistance(const Vector &a, const Vector &b)
Computes the 2D distance between two 3D vectors.
static std::tuple< double, double > GetQuantizedElevationAngle(Ptr< const MobilityModel > a, Ptr< const MobilityModel > b)
Computes and quantizes the elevation angle to a two-digits integer in [10, 90].
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the Indoor Office scenario...
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
Implements the pathloss model defined in 3GPP TR 38.811, Table ?
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
const std::map< int, std::vector< float > > * m_SFCL_DenseUrban
The nested map containing the Shadow Fading and Clutter Loss values for the NTN Dense Urban scenario.
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
Implements the pathloss model defined in 3GPP TR 38.811, Table ?
const std::map< int, std::vector< float > > * m_SFCL_SuburbanRural
The nested map containing the Shadow Fading and Clutter Loss values for the NTN Suburban and Rural sc...
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
Implements the pathloss model defined in 3GPP TR 38.811, Table ?
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
const std::map< int, std::vector< float > > * m_SFCL_SuburbanRural
The nested map containing the Shadow Fading and Clutter Loss values for the NTN Suburban and Rural sc...
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
Implements the pathloss model defined in 3GPP TR 38.811, Table ?
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
const std::map< int, std::vector< float > > * m_SFCL_Urban
The nested map containing the Shadow Fading and Clutter Loss values for the NTN Urban scenario.
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
Ptr< ChannelConditionModel > GetChannelConditionModel() const
Returns the associated channel condition model.
virtual double GetO2iLowPenetrationLoss(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const
Retrieves the o2i building penetration loss value by looking at m_o2iLossMap.
Ptr< UniformRandomVariable > m_randomO2iVar2
a uniform random variable for the calculation of the indoor loss, see TR38.901 Table 7....
double m_meanVehicleO2iLoss
normal cars (9dB), cars with metal coated glass panels (20dB)
double GetFrequency() const
Return the current central frequency.
double GetLoss(Ptr< ChannelCondition > cond, Ptr< MobilityModel > a, Ptr< MobilityModel > b) const
Computes the pathloss between a and b.
Ptr< UniformRandomVariable > m_randomO2iVar1
a uniform random variable for the calculation of the indoor loss, see TR38.901 Table 7....
double GetShadowing(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const
Retrieves the shadowing value by looking at m_shadowingMap.
static double Calculate2dDistance(Vector a, Vector b)
Computes the 2D distance between two 3D vectors.
void SetChannelConditionModel(Ptr< ChannelConditionModel > model)
Set the channel condition model used to determine the channel state (e.g., the LOS/NLOS condition).
std::unordered_map< uint32_t, ShadowingMapItem > m_shadowingMap
map to store the shadowing values
virtual double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const =0
Computes the pathloss between a and b considering that the line of sight is obstructed.
virtual bool DoIsO2iLowPenetrationLoss(Ptr< const ChannelCondition > cond) const
Indicates the condition of the o2i building penetration loss (defined in 3GPP TR 38....
int64_t DoAssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
virtual double GetLossNlosv(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const
Computes the pathloss between a and b considering that the line of sight is obstructed by a vehicle.
Ptr< NormalRandomVariable > m_normalO2iVehicularLossVar
a normal random variable for the calculation of penetration loss for vehicles see TR38....
virtual double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const =0
Returns the shadow fading correlation distance.
Ptr< NormalRandomVariable > m_normRandomVariable
normal random variable
Ptr< ChannelConditionModel > m_channelConditionModel
pointer to the channel condition model
std::unordered_map< uint32_t, O2iLossMapItem > m_o2iLossMap
map to store the o2i Loss values
virtual double GetO2iDistance2dIn() const =0
Returns the minimum of the two independently generated distances according to the uniform distributio...
std::unordered_map< uint32_t, double > m_o2iVehicularUtLossMap
vehicular O2I loss for each individual UT with speed x, such that 30 < x <= 120 km/h.
virtual double GetO2iHighPenetrationLoss(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const
Retrieves the o2i building penetration loss value by looking at m_o2iLossMap.
bool IsO2iLowPenetrationLoss(Ptr< const ChannelCondition > cond) const
Return true if the O2I Building Penetration loss corresponds to a low loss condition.
virtual double GetO2iDistance2dInSub6Ghz() const
Returns a a single, link-specific, uniformly distributed variable value depending on the specific 3GP...
void SetFrequency(double f)
Set the central frequency of the model.
void ClearO2iLossCacheMap()
Clear cached O2I Building Penetration loss.
void DoDispose() override
Destructor implementation.
static uint32_t GetKey(Ptr< MobilityModel > a, Ptr< MobilityModel > b)
Returns an unique key for the channel between a and b.
Ptr< NormalRandomVariable > m_normalO2iLowLossVar
a normal random variable for the calculation of 02i low loss, see TR38.901 Table 7....
bool m_enforceRanges
strictly enforce TR 38.901 parameter ranges
virtual double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const =0
Returns the shadow fading standard deviation.
Ptr< NormalRandomVariable > m_normalO2iHighLossVar
a normal random variable for the calculation of 02i high loss, see TR38.901 Table 7....
double DoCalcRxPower(double txPowerDbm, Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the received power by applying the pathloss model described in 3GPP TR 38....
double GetO2iSub6GhzPenetrationLoss(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const
Retrieves the o2i building penetration loss value by looking at m_o2iLossMap.
static Vector GetVectorDifference(Ptr< MobilityModel > a, Ptr< MobilityModel > b)
Get the difference between the node position.
bool m_buildingPenLossesEnabled
enable/disable building penetration losses
double GetO2iVehicularLoss(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::O2iConditionValue cond) const
Computes the o2i vehicular penetration loss by looking at m_o2iVehicularUtLossMap.
virtual double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const =0
Computes the pathloss between a and b considering that the line of sight is not obstructed.
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the RMa scenario.
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
static double Pl1(double frequency, double distance3D, double h, double w)
Computes the PL1 formula for the RMa scenario.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
double m_h
average building height in meters
static double GetBpDistance(double frequency, double hA, double hB)
Computes the breakpoint distance for the RMa scenario.
bool DoIsO2iLowPenetrationLoss(Ptr< const ChannelCondition > cond) const override
Indicates the condition of the o2i building penetration loss (defined in 3GPP TR 38....
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the UMa scenario.
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
double GetBpDistance(double hUt, double hBs, double distance2D) const
Computes the breakpoint distance.
int64_t DoAssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
Ptr< UniformRandomVariable > m_uniformVar
a uniform random variable used for the computation of the breakpoint distance
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetO2iDistance2dInSub6Ghz() const override
Returns a a single, link-specific, uniformly distributed variable value depending on the specific 3GP...
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the UMi-Street Canyon scen...
double GetO2iDistance2dInSub6Ghz() const override
Returns a a single, link-specific, uniformly distributed variable value depending on the specific 3GP...
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetBpDistance(double hUt, double hBs, double distance2D) const
Computes the breakpoint distance.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
a 2d vector
Definition vector.h:196
double GetLength() const
Compute the length (magnitude) of the vector.
Definition vector.cc:77
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:114
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeChecker > MakeDoubleChecker()
Definition double.h:82
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition double.h:32
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition pointer.h:249
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:270
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition abort.h:133
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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.
Definition log.h:250
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
const std::map< int, std::vector< float > > SFCL_SuburbanRural
The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the NTN Suburba...
double ComputeIonosphericPlusTroposphericScintillationLoss(double freq, double elevAngleQuantized)
Computes the ionospheric plus tropospheric scintillation loss using the formulas described in 3GPP TR...
std::tuple< double, double, double, double > GetBsUtDistancesAndHeights(ns3::Ptr< const ns3::MobilityModel > a, ns3::Ptr< const ns3::MobilityModel > b)
Get the base station and user terminal relative distances and heights.
double ComputeAtmosphericAbsorptionLoss(double freq, double elevAngle)
Computes the atmospheric absorption loss using the formula described in 3GPP TR 38....
double ComputeNtnPathloss(double freq, double dist3d)
Computes the free-space path loss using the formula described in 3GPP TR 38.811, Table 6....
const double atmosphericAbsorption[101]
Array containing the attenuation given by atmospheric absorption.
const std::map< int, float > troposphericScintillationLoss
Map containing the Tropospheric attenuation in dB with 99% probability at 20 GHz in Toulouse used for...
const std::map< int, std::vector< float > > SFCL_Urban
The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the NTN Urban s...
double ComputeClutterLoss(double freq, const std::map< int, std::vector< float > > *sfcl, double elevAngleQuantized)
Computes the clutter loss using the formula described in 3GPP TR 38.811, Sec 6.6.6....
SFCL_params
The enumerator used for code clarity when performing parameter assignment in the GetLoss Methods.
std::tuple< double, double > GetBsUtHeightsUmiStreetCanyon(double heightA, double heightB)
Get the base station and user terminal heights for the UmiStreetCanyon scenario.
const std::map< int, std::vector< float > > SFCL_DenseUrban
The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the NTN Dense U...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double CalculateDistance(const Vector3D &a, const Vector3D &b)
Definition vector.cc:98