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 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
20
22
23#include "ns3/boolean.h"
24#include "ns3/double.h"
25#include "ns3/geocentric-constant-position-mobility-model.h"
26#include "ns3/log.h"
27#include "ns3/mobility-model.h"
28#include "ns3/node.h"
29#include "ns3/pointer.h"
30#include "ns3/simulator.h"
31
32#include <cmath>
33
34namespace
35{
36/**
37 * The enumerator used for code clarity when performing parameter assignment in the GetLoss Methods
38 */
40{
47};
48
49/**
50 * The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the
51 * NTN Dense Urban scenario
52 */
53const std::map<int, std::vector<float>> SFCL_DenseUrban{
54 {10, {3.5, 15.5, 34.3, 2.9, 17.1, 44.3}},
55 {20, {3.4, 13.9, 30.9, 2.4, 17.1, 39.9}},
56 {30, {2.9, 12.4, 29.0, 2.7, 15.6, 37.5}},
57 {40, {3.0, 11.7, 27.7, 2.4, 14.6, 35.8}},
58 {50, {3.1, 10.6, 26.8, 2.4, 14.2, 34.6}},
59 {60, {2.7, 10.5, 26.2, 2.7, 12.6, 33.8}},
60 {70, {2.5, 10.1, 25.8, 2.6, 12.1, 33.3}},
61 {80, {2.3, 9.2, 25.5, 2.8, 12.3, 33.0}},
62 {90, {1.2, 9.2, 25.5, 0.6, 12.3, 32.9}},
63};
64
65/**
66 * The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the
67 * NTN Urban scenario
68 */
69const std::map<int, std::vector<float>> SFCL_Urban{
70 {10, {4, 6, 34.3, 4, 6, 44.3}},
71 {20, {4, 6, 30.9, 4, 6, 39.9}},
72 {30, {4, 6, 29.0, 4, 6, 37.5}},
73 {40, {4, 6, 27.7, 4, 6, 35.8}},
74 {50, {4, 6, 26.8, 4, 6, 34.6}},
75 {60, {4, 6, 26.2, 4, 6, 33.8}},
76 {70, {4, 6, 25.8, 4, 6, 33.3}},
77 {80, {4, 6, 25.5, 4, 6, 33.0}},
78 {90, {4, 6, 25.5, 4, 6, 32.9}},
79};
80
81/**
82 * The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the
83 * NTN Suburban and Rural scenarios
84 */
85const std::map<int, std::vector<float>> SFCL_SuburbanRural{
86 {10, {1.79, 8.93, 19.52, 1.9, 10.7, 29.5}},
87 {20, {1.14, 9.08, 18.17, 1.6, 10.0, 24.6}},
88 {30, {1.14, 8.78, 18.42, 1.9, 11.2, 21.9}},
89 {40, {0.92, 10.25, 18.28, 2.3, 11.6, 20.0}},
90 {50, {1.42, 10.56, 18.63, 2.7, 11.8, 18.7}},
91 {60, {1.56, 10.74, 17.68, 3.1, 10.8, 17.8}},
92 {70, {0.85, 10.17, 16.5, 3.0, 10.8, 17.2}},
93 {80, {0.72, 11.52, 16.3, 3.6, 10.8, 16.9}},
94 {90, {0.72, 11.52, 16.3, 0.4, 10.8, 16.8}},
95};
96
97/**
98 * Array containing the attenuation given by atmospheric absorption. 100 samples are selected for
99 * frequencies from 1GHz to 100GHz. In order to get the atmospheric absorption loss for a given
100 * frequency f: 1- round f to the closest integer between 0 and 100. 2- use the obtained integer to
101 * access the corresponding element in the array, that will give the attenuation at that frequency.
102 * Data is obtained form ITU-R P.676 Figure 6.
103 */
104const double atmosphericAbsorption[101] = {
105 0, 0.0300, 0.0350, 0.0380, 0.0390, 0.0410, 0.0420, 0.0450, 0.0480, 0.0500,
106 0.0530, 0.0587, 0.0674, 0.0789, 0.0935, 0.1113, 0.1322, 0.1565, 0.1841, 0.2153,
107 0.2500, 0.3362, 0.4581, 0.5200, 0.5200, 0.5000, 0.4500, 0.3850, 0.3200, 0.2700,
108 0.2500, 0.2517, 0.2568, 0.2651, 0.2765, 0.2907, 0.3077, 0.3273, 0.3493, 0.3736,
109 0.4000, 0.4375, 0.4966, 0.5795, 0.6881, 0.8247, 0.9912, 1.1900, 1.4229, 1.6922,
110 2.0000, 4.2654, 10.1504, 19.2717, 31.2457, 45.6890, 62.2182, 80.4496, 100.0000, 140.0205,
111 170.0000, 100.0000, 78.1682, 59.3955, 43.5434, 30.4733, 20.0465, 12.1244, 6.5683, 3.2397,
112 2.0000, 1.7708, 1.5660, 1.3858, 1.2298, 1.0981, 0.9905, 0.9070, 0.8475, 0.8119,
113 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000,
114 0.8000, 0.8029, 0.8112, 0.8243, 0.8416, 0.8625, 0.8864, 0.9127, 0.9408, 0.9701,
115 1.0000};
116
117/**
118 * Map containing the Tropospheric attenuation in dB with 99% probability at 20 GHz in Toulouse
119 * used for tropospheric scintillation losses. From Table 6.6.6.2.1-1 of 3GPP TR 38.811.
120 */
121const std::map<int, float> troposphericScintillationLoss{
122 {10, {1.08}},
123 {20, {0.48}},
124 {30, {0.30}},
125 {40, {0.22}},
126 {50, {0.17}},
127 {60, {0.13}},
128 {70, {0.12}},
129 {80, {0.12}},
130 {90, {0.12}},
131};
132
133/**
134 * @brief Get the base station and user terminal relative distances and heights
135 *
136 * @param a the mobility model of terminal a
137 * @param b the mobility model of terminal b
138 *
139 * @return The tuple [dist2D, dist3D, hBs, hUt], where dist2D and dist3D
140 * are the 2D and 3D distances between a and b, respectively, hBs is the bigger
141 * height and hUt the smallest.
142 */
143std::tuple<double, double, double, double>
146{
147 auto aPos = a->GetPosition();
148 auto bPos = b->GetPosition();
149 double distance2D = ns3::ThreeGppChannelConditionModel::Calculate2dDistance(aPos, bPos);
150 double distance3D = ns3::CalculateDistance(aPos, bPos);
151 double hBs = std::max(aPos.z, bPos.z);
152 double hUt = std::min(aPos.z, bPos.z);
153 return std::make_tuple(distance2D, distance3D, hBs, hUt);
154};
155
156/**
157 * @brief Get the base station and user terminal heights for the UmiStreetCanyon scenario
158 *
159 * @param heightA the first height in meters
160 * @param heightB the second height in meters
161 *
162 * @return The tuple [hBs, hUt], where hBs is assumed to be = 10 and hUt other height.
163 */
164std::tuple<double, double>
165GetBsUtHeightsUmiStreetCanyon(double heightA, double heightB)
166{
167 double hBs = (heightA == 10) ? heightA : heightB;
168 double hUt = (heightA == 10) ? heightB : heightA;
169 return std::make_tuple(hBs, hUt);
170};
171
172/**
173 * @brief Computes the free-space path loss using the formula described in 3GPP TR 38.811,
174 * Table 6.6.2
175 *
176 * @param freq the operating frequency
177 * @param dist3d the 3D distance between the communicating nodes
178 *
179 * @return the path loss for NTN scenarios
180 */
181double
182ComputeNtnPathloss(double freq, double dist3d)
183{
184 return 32.45 + 20 * log10(freq / 1e9) + 20 * log10(dist3d);
185};
186
187/**
188 * @brief Computes the atmospheric absorption loss using the formula described in 3GPP TR 38.811,
189 * Sec 6.6.4
190 *
191 * @param freq the operating frequency
192 * @param elevAngle the elevation angle between the communicating nodes
193 *
194 * @return the atmospheric absorption loss for NTN scenarios
195 */
196double
197ComputeAtmosphericAbsorptionLoss(double freq, double elevAngle)
198{
199 double loss = 0;
200 if ((elevAngle < 10 && freq > 1e9) || freq >= 10e9)
201 {
202 int roundedFreq = round(freq / 10e8);
203 loss += atmosphericAbsorption[roundedFreq] / sin(elevAngle * (M_PI / 180));
204 }
205
206 return loss;
207};
208
209/**
210 * @brief Computes the ionospheric plus tropospheric scintillation loss using the formulas
211 * described in 3GPP TR 38.811, Sec 6.6.6.1-4 and 6.6.6.2, respectively.
212 *
213 * @param freq the operating frequency
214 * @param elevAngleQuantized the quantized elevation angle between the communicating nodes
215 *
216 * @return the ionospheric plus tropospheric scintillation loss for NTN scenarios
217 */
218double
219ComputeIonosphericPlusTroposphericScintillationLoss(double freq, double elevAngleQuantized)
220{
221 double loss = 0;
222 if (freq < 6e9)
223 {
224 // Ionospheric
225 loss = 6.22 / (pow(freq / 1e9, 1.5));
226 }
227 else
228 {
229 // Tropospheric
230 loss = troposphericScintillationLoss.at(elevAngleQuantized);
231 }
232 return loss;
233};
234
235/**
236 * @brief Computes the clutter loss using the formula
237 * described in 3GPP TR 38.811, Sec 6.6.6.1-4 and 6.6.6.2, respectively.
238 *
239 * @param freq the operating frequency
240 * @param elevAngleQuantized the quantized elevation angle between the communicating nodes
241 * @param sfcl the nested map containing the Shadow Fading and
242 * Clutter Loss values for the NTN Suburban and Rural scenario
243 *
244 * @return the clutter loss for NTN scenarios
245 */
246double
248 const std::map<int, std::vector<float>>* sfcl,
249 double elevAngleQuantized)
250{
251 double loss = 0;
252 if (freq < 13.0e9)
253 {
254 loss += (*sfcl).at(elevAngleQuantized)[SFCL_params::S_NLOS_CL]; // Get the Clutter Loss for
255 // the S Band
256 }
257 else
258 {
259 loss += (*sfcl).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_CL]; // Get the Clutter Loss for
260 // the Ka Band
261 }
262
263 return loss;
264};
265
266constexpr double M_C = 3.0e8; //!< propagation velocity in free space
267
268} // namespace
269
270namespace ns3
271{
272
273NS_LOG_COMPONENT_DEFINE("ThreeGppPropagationLossModel");
274
275NS_OBJECT_ENSURE_REGISTERED(ThreeGppPropagationLossModel);
276
277TypeId
279{
280 static TypeId tid =
281 TypeId("ns3::ThreeGppPropagationLossModel")
283 .SetGroupName("Propagation")
284 .AddAttribute("Frequency",
285 "The centre frequency in Hz.",
286 DoubleValue(500.0e6),
289 MakeDoubleChecker<double>())
290 .AddAttribute("ShadowingEnabled",
291 "Enable/disable shadowing.",
292 BooleanValue(true),
295 .AddAttribute(
296 "ChannelConditionModel",
297 "Pointer to the channel condition model.",
298 PointerValue(),
301 MakePointerChecker<ChannelConditionModel>())
302 .AddAttribute("EnforceParameterRanges",
303 "Whether to strictly enforce TR38.901 applicability ranges",
304 BooleanValue(false),
307 .AddAttribute(
308 "BuildingPenetrationLossesEnabled",
309 "Enable/disable Building Penetration Losses.",
310 BooleanValue(true),
313 return tid;
314}
315
318{
319 NS_LOG_FUNCTION(this);
320
321 // initialize the normal random variables
322 m_normRandomVariable = CreateObject<NormalRandomVariable>();
323 m_normRandomVariable->SetAttribute("Mean", DoubleValue(0));
324 m_normRandomVariable->SetAttribute("Variance", DoubleValue(1));
325
326 m_randomO2iVar1 = CreateObject<UniformRandomVariable>();
327 m_randomO2iVar2 = CreateObject<UniformRandomVariable>();
328
329 m_normalO2iLowLossVar = CreateObject<NormalRandomVariable>();
330 m_normalO2iLowLossVar->SetAttribute("Mean", DoubleValue(0));
331 m_normalO2iLowLossVar->SetAttribute("Variance", DoubleValue(4.4));
332
333 m_normalO2iHighLossVar = CreateObject<NormalRandomVariable>();
334 m_normalO2iHighLossVar->SetAttribute("Mean", DoubleValue(0));
335 m_normalO2iHighLossVar->SetAttribute("Variance", DoubleValue(6.5));
336}
337
339{
340 NS_LOG_FUNCTION(this);
341}
342
343void
345{
346 m_channelConditionModel->Dispose();
347 m_channelConditionModel = nullptr;
348 m_shadowingMap.clear();
349}
350
351void
353{
354 NS_LOG_FUNCTION(this);
356}
357
360{
361 NS_LOG_FUNCTION(this);
363}
364
365void
367{
368 NS_LOG_FUNCTION(this);
369 NS_ASSERT_MSG(f >= 500.0e6 && f <= 100.0e9,
370 "Frequency should be between 0.5 and 100 GHz but is " << f);
371 m_frequency = f;
372}
373
374double
376{
377 NS_LOG_FUNCTION(this);
378 return m_frequency;
379}
380
381bool
383{
384 return DoIsO2iLowPenetrationLoss(cond);
385}
386
387double
390 Ptr<MobilityModel> b) const
391{
392 NS_LOG_FUNCTION(this);
393
394 // check if the model is initialized
395 NS_ASSERT_MSG(m_frequency != 0.0, "First set the centre frequency");
396
397 // retrieve the channel condition
398 NS_ASSERT_MSG(m_channelConditionModel, "First set the channel condition model");
399 Ptr<ChannelCondition> cond = m_channelConditionModel->GetChannelCondition(a, b);
400
401 double rxPow = txPowerDbm;
402 rxPow -= GetLoss(cond, a, b);
403
405 {
406 rxPow -= GetShadowing(a, b, cond->GetLosCondition());
407 }
408
409 // get o2i losses
411 ((cond->GetO2iCondition() == ChannelCondition::O2iConditionValue::O2I) ||
412 (cond->GetO2iCondition() == ChannelCondition::O2iConditionValue::I2I &&
413 cond->GetLosCondition() == ChannelCondition::LosConditionValue::NLOS)))
414 {
415 if (IsO2iLowPenetrationLoss(cond))
416 {
417 rxPow -= GetO2iLowPenetrationLoss(a, b, cond->GetLosCondition());
418 }
419 else
420 {
421 rxPow -= GetO2iHighPenetrationLoss(a, b, cond->GetLosCondition());
422 }
423 }
424
425 return rxPow;
426}
427
428double
431 Ptr<MobilityModel> b) const
432{
433 NS_LOG_FUNCTION(this);
434
435 double loss = 0;
436 switch (cond->GetLosCondition())
437 {
439 loss = GetLossLos(a, b);
440 break;
442 loss = GetLossNlosv(a, b);
443 break;
445 loss = GetLossNlos(a, b);
446 break;
447 default:
448 NS_FATAL_ERROR("Unknown channel condition");
449 }
450
451 return loss;
452}
453
454double
459{
460 NS_LOG_FUNCTION(this);
461
462 double o2iLossValue = 0;
463 double lowLossTw = 0;
464 double lossIn = 0;
465 double lowlossNormalVariate = 0;
466 double lGlass = 0;
467 double lConcrete = 0;
468
469 // compute the channel key
470 uint32_t key = GetKey(a, b);
471
472 bool notFound = false; // indicates if the o2iLoss value has not been computed yet
473 bool newCondition = false; // indicates if the channel condition has changed
474
475 auto it = m_o2iLossMap.end(); // the o2iLoss map iterator
476 if (m_o2iLossMap.find(key) != m_o2iLossMap.end())
477 {
478 // found the o2iLoss value in the map
479 it = m_o2iLossMap.find(key);
480 newCondition = (it->second.m_condition != cond); // true if the condition changed
481 }
482 else
483 {
484 notFound = true;
485 // add a new entry in the map and update the iterator
486 O2iLossMapItem newItem;
487 it = m_o2iLossMap.insert(it, std::make_pair(key, newItem));
488 }
489
490 if (notFound || newCondition)
491 {
492 // distance2dIn is minimum of two independently generated uniformly distributed
493 // variables between 0 and 25 m for UMa and UMi-Street Canyon, and between 0 and
494 // 10 m for RMa. 2D−in d shall be UT-specifically generated.
495 double distance2dIn = GetO2iDistance2dIn();
496
497 // calculate material penetration losses, see TR 38.901 Table 7.4.3-1
498 lGlass = 2 + 0.2 * m_frequency / 1e9; // m_frequency is operation frequency in Hz
499 lConcrete = 5 + 4 * m_frequency / 1e9;
500
501 lowLossTw =
502 5 - 10 * log10(0.3 * std::pow(10, -lGlass / 10) + 0.7 * std::pow(10, -lConcrete / 10));
503
504 // calculate indoor loss
505 lossIn = 0.5 * distance2dIn;
506
507 // calculate low loss standard deviation
508 lowlossNormalVariate = m_normalO2iLowLossVar->GetValue();
509
510 o2iLossValue = lowLossTw + lossIn + lowlossNormalVariate;
511 }
512 else
513 {
514 o2iLossValue = it->second.m_o2iLoss;
515 }
516
517 // update the entry in the map
518 it->second.m_o2iLoss = o2iLossValue;
519 it->second.m_condition = cond;
520
521 return o2iLossValue;
522}
523
524double
529{
530 NS_LOG_FUNCTION(this);
531
532 double o2iLossValue = 0;
533 double highLossTw = 0;
534 double lossIn = 0;
535 double highlossNormalVariate = 0;
536 double lIIRGlass = 0;
537 double lConcrete = 0;
538
539 // compute the channel key
540 uint32_t key = GetKey(a, b);
541
542 bool notFound = false; // indicates if the o2iLoss value has not been computed yet
543 bool newCondition = false; // indicates if the channel condition has changed
544
545 auto it = m_o2iLossMap.end(); // the o2iLoss map iterator
546 if (m_o2iLossMap.find(key) != m_o2iLossMap.end())
547 {
548 // found the o2iLoss value in the map
549 it = m_o2iLossMap.find(key);
550 newCondition = (it->second.m_condition != cond); // true if the condition changed
551 }
552 else
553 {
554 notFound = true;
555 // add a new entry in the map and update the iterator
556 O2iLossMapItem newItem;
557 it = m_o2iLossMap.insert(it, std::make_pair(key, newItem));
558 }
559
560 if (notFound || newCondition)
561 {
562 // generate a new independent realization
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 lIIRGlass = 23 + 0.3 * m_frequency / 1e9;
571 lConcrete = 5 + 4 * m_frequency / 1e9;
572
573 highLossTw = 5 - 10 * log10(0.7 * std::pow(10, -lIIRGlass / 10) +
574 0.3 * std::pow(10, -lConcrete / 10));
575
576 // calculate indoor loss
577 lossIn = 0.5 * distance2dIn;
578
579 // calculate low loss standard deviation
580 highlossNormalVariate = m_normalO2iHighLossVar->GetValue();
581
582 o2iLossValue = highLossTw + lossIn + highlossNormalVariate;
583 }
584 else
585 {
586 o2iLossValue = it->second.m_o2iLoss;
587 }
588
589 // update the entry in the map
590 it->second.m_o2iLoss = o2iLossValue;
591 it->second.m_condition = cond;
592
593 return o2iLossValue;
594}
595
596bool
598{
599 if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::LOW)
600 {
601 return true;
602 }
603 else if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::HIGH)
604 {
605 return false;
606 }
607 else
608 {
609 NS_ABORT_MSG("If we have set the O2I condition, we shouldn't be here");
610 }
611}
612
613double
615{
616 NS_LOG_FUNCTION(this);
617 NS_FATAL_ERROR("Unsupported channel condition (NLOSv)");
618 return 0;
619}
620
621double
625{
626 NS_LOG_FUNCTION(this);
627
628 double shadowingValue;
629
630 // compute the channel key
631 uint32_t key = GetKey(a, b);
632
633 bool notFound = false; // indicates if the shadowing value has not been computed yet
634 bool newCondition = false; // indicates if the channel condition has changed
635 Vector newDistance; // the distance vector, that is not a distance but a difference
636 auto it = m_shadowingMap.end(); // the shadowing map iterator
637 if (m_shadowingMap.find(key) != m_shadowingMap.end())
638 {
639 // found the shadowing value in the map
640 it = m_shadowingMap.find(key);
641 newDistance = GetVectorDifference(a, b);
642 newCondition = (it->second.m_condition != cond); // true if the condition changed
643 }
644 else
645 {
646 notFound = true;
647
648 // add a new entry in the map and update the iterator
649 ShadowingMapItem newItem;
650 it = m_shadowingMap.insert(it, std::make_pair(key, newItem));
651 }
652
653 if (notFound || newCondition)
654 {
655 // generate a new independent realization
656 shadowingValue = m_normRandomVariable->GetValue() * GetShadowingStd(a, b, cond);
657 }
658 else
659 {
660 // compute a new correlated shadowing loss
661 Vector2D displacement(newDistance.x - it->second.m_distance.x,
662 newDistance.y - it->second.m_distance.y);
663 double R = exp(-1 * displacement.GetLength() / GetShadowingCorrelationDistance(cond));
664 shadowingValue = R * it->second.m_shadowing + sqrt(1 - R * R) *
665 m_normRandomVariable->GetValue() *
666 GetShadowingStd(a, b, cond);
667 }
668
669 // update the entry in the map
670 it->second.m_shadowing = shadowingValue;
671 it->second.m_distance = newDistance; // Save the (0,0,0) vector in case it's the first time we
672 // are calculating this value
673 it->second.m_condition = cond;
674
675 return shadowingValue;
676}
677
678int64_t
680{
681 NS_LOG_FUNCTION(this);
682
683 m_normRandomVariable->SetStream(stream);
684 m_randomO2iVar1->SetStream(stream + 1);
685 m_randomO2iVar2->SetStream(stream + 2);
686 m_normalO2iLowLossVar->SetStream(stream + 3);
687 m_normalO2iHighLossVar->SetStream(stream + 4);
688
689 return 5;
690}
691
692double
694{
695 double x = a.x - b.x;
696 double y = a.y - b.y;
697 double distance2D = sqrt(x * x + y * y);
698
699 return distance2D;
700}
701
704{
705 // use the nodes ids to obtain an unique key for the channel between a and b
706 // sort the nodes ids so that the key is reciprocal
707 uint32_t x1 = std::min(a->GetObject<Node>()->GetId(), b->GetObject<Node>()->GetId());
708 uint32_t x2 = std::max(a->GetObject<Node>()->GetId(), b->GetObject<Node>()->GetId());
709
710 // use the cantor function to obtain the key
711 uint32_t key = (((x1 + x2) * (x1 + x2 + 1)) / 2) + x2;
712
713 return key;
714}
715
716Vector
718{
719 uint32_t x1 = a->GetObject<Node>()->GetId();
720 uint32_t x2 = b->GetObject<Node>()->GetId();
721
722 if (x1 < x2)
723 {
724 return b->GetPosition() - a->GetPosition();
725 }
726 else
727 {
728 return a->GetPosition() - b->GetPosition();
729 }
730}
731
732// ------------------------------------------------------------------------- //
733
735
736TypeId
738{
739 static TypeId tid = TypeId("ns3::ThreeGppRmaPropagationLossModel")
741 .SetGroupName("Propagation")
742 .AddConstructor<ThreeGppRmaPropagationLossModel>()
743 .AddAttribute("AvgBuildingHeight",
744 "The average building height in meters.",
745 DoubleValue(5.0),
747 MakeDoubleChecker<double>(5.0, 50.0))
748 .AddAttribute("AvgStreetWidth",
749 "The average street width in meters.",
750 DoubleValue(20.0),
752 MakeDoubleChecker<double>(5.0, 50.0));
753 return tid;
754}
755
758{
759 NS_LOG_FUNCTION(this);
760
761 // set a default channel condition model
762 m_channelConditionModel = CreateObject<ThreeGppRmaChannelConditionModel>();
763}
764
766{
767 NS_LOG_FUNCTION(this);
768}
769
770double
772{
773 // distance2dIn is minimum of two independently generated uniformly distributed variables
774 // between 0 and 10 m for RMa. 2D−in d shall be UT-specifically generated.
775 return std::min(m_randomO2iVar1->GetValue(0, 10), m_randomO2iVar2->GetValue(0, 10));
776}
777
778bool
780 [[maybe_unused]]) const
781{
782 // Based on 3GPP 38.901 7.4.3.1 in RMa only low losses are applied.
783 // Therefore enforce low losses.
784 return true;
785}
786
787double
789{
790 NS_LOG_FUNCTION(this);
791 NS_ASSERT_MSG(m_frequency <= 30.0e9,
792 "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
793
794 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
795
796 // check if hBS and hUT are within the specified validity range
797 if (hUt < 1.0 || hUt > 10.0)
798 {
799 NS_ABORT_MSG_IF(m_enforceRanges, "Rma UT height out of range");
801 "The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
802 }
803
804 if (hBs < 10.0 || hBs > 150.0)
805 {
806 NS_ABORT_MSG_IF(m_enforceRanges, "Rma BS height out of range");
808 "The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
809 }
810
811 // NOTE The model is intended to be used for BS-UT links, however we may need to
812 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
813 // interference. In order to apply the model, we need to retrieve the values of
814 // hBS and hUT, but in these cases one of the two falls outside the validity
815 // range and the warning message is printed (hBS for the UT-UT case and hUT
816 // for the BS-BS case).
817
818 double distanceBp = GetBpDistance(m_frequency, hBs, hUt);
819 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
821 distanceBp > 0,
822 "Breakpoint distance is zero (divide-by-zero below); are either hBs or hUt = 0?");
823
824 // check if the distance is outside the validity range
825 if (distance2D < 10.0 || distance2D > 10.0e3)
826 {
827 NS_ABORT_MSG_IF(m_enforceRanges, "Rma distance2D out of range");
828 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
829 "accurate");
830 }
831
832 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
833 double loss = 0;
834 if (distance2D <= distanceBp)
835 {
836 // use PL1
837 loss = Pl1(m_frequency, distance3D, m_h, m_w);
838 }
839 else
840 {
841 // use PL2
842 loss = Pl1(m_frequency, distanceBp, m_h, m_w) + 40 * log10(distance3D / distanceBp);
843 }
844
845 NS_LOG_DEBUG("Loss " << loss);
846
847 return loss;
848}
849
850double
852{
853 NS_LOG_FUNCTION(this);
854 NS_ASSERT_MSG(m_frequency <= 30.0e9,
855 "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
856
857 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
858
859 // check if hBs and hUt are within the validity range
860 if (hUt < 1.0 || hUt > 10.0)
861 {
862 NS_ABORT_MSG_IF(m_enforceRanges, "Rma UT height out of range");
864 "The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
865 }
866
867 if (hBs < 10.0 || hBs > 150.0)
868 {
869 NS_ABORT_MSG_IF(m_enforceRanges, "Rma BS height out of range");
871 "The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
872 }
873
874 // NOTE The model is intended to be used for BS-UT links, however we may need to
875 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
876 // interference. In order to apply the model, we need to retrieve the values of
877 // hBS and hUT, but in these cases one of the two falls outside the validity
878 // range and the warning message is printed (hBS for the UT-UT case and hUT
879 // for the BS-BS case).
880
881 // check if the distance is outside the validity range
882 if (distance2D < 10.0 || distance2D > 5.0e3)
883 {
884 NS_ABORT_MSG_IF(m_enforceRanges, "distance2D out of range");
885 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
886 "accurate");
887 }
888
889 // compute the pathloss
890 double plNlos = 161.04 - 7.1 * log10(m_w) + 7.5 * log10(m_h) -
891 (24.37 - 3.7 * pow((m_h / hBs), 2)) * log10(hBs) +
892 (43.42 - 3.1 * log10(hBs)) * (log10(distance3D) - 3.0) +
893 20.0 * log10(m_frequency / 1e9) - (3.2 * pow(log10(11.75 * hUt), 2) - 4.97);
894
895 double loss = std::max(GetLossLos(a, b), plNlos);
896
897 NS_LOG_DEBUG("Loss " << loss);
898
899 return loss;
900}
901
902double
906{
907 NS_LOG_FUNCTION(this);
908 double shadowingStd;
909
911 {
912 // compute the 2D distance between the two nodes
913 double distance2d = Calculate2dDistance(a->GetPosition(), b->GetPosition());
914
915 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 5)
916 double distanceBp = GetBpDistance(m_frequency, a->GetPosition().z, b->GetPosition().z);
917
918 if (distance2d <= distanceBp)
919 {
920 shadowingStd = 4.0;
921 }
922 else
923 {
924 shadowingStd = 6.0;
925 }
926 }
928 {
929 shadowingStd = 8.0;
930 }
931 else
932 {
933 NS_FATAL_ERROR("Unknown channel condition");
934 }
935
936 return shadowingStd;
937}
938
939double
942{
943 NS_LOG_FUNCTION(this);
944 double correlationDistance;
945
946 // See 3GPP TR 38.901, Table 7.5-6
948 {
949 correlationDistance = 37;
950 }
952 {
953 correlationDistance = 120;
954 }
955 else
956 {
957 NS_FATAL_ERROR("Unknown channel condition");
958 }
959
960 return correlationDistance;
961}
962
963double
964ThreeGppRmaPropagationLossModel::Pl1(double frequency, double distance3D, double h, double /* w */)
965{
966 double loss = 20.0 * log10(40.0 * M_PI * distance3D * frequency / 1e9 / 3.0) +
967 std::min(0.03 * pow(h, 1.72), 10.0) * log10(distance3D) -
968 std::min(0.044 * pow(h, 1.72), 14.77) + 0.002 * log10(h) * distance3D;
969 return loss;
970}
971
972double
973ThreeGppRmaPropagationLossModel::GetBpDistance(double frequency, double hA, double hB)
974{
975 double distanceBp = 2.0 * M_PI * hA * hB * frequency / M_C;
976 return distanceBp;
977}
978
979// ------------------------------------------------------------------------- //
980
982
983TypeId
985{
986 static TypeId tid = TypeId("ns3::ThreeGppUmaPropagationLossModel")
988 .SetGroupName("Propagation")
989 .AddConstructor<ThreeGppUmaPropagationLossModel>();
990 return tid;
991}
992
995{
996 NS_LOG_FUNCTION(this);
997 m_uniformVar = CreateObject<UniformRandomVariable>();
998 // set a default channel condition model
999 m_channelConditionModel = CreateObject<ThreeGppUmaChannelConditionModel>();
1000}
1001
1003{
1004 NS_LOG_FUNCTION(this);
1005}
1006
1007double
1008ThreeGppUmaPropagationLossModel::GetBpDistance(double hUt, double hBs, double distance2D) const
1009{
1010 NS_LOG_FUNCTION(this);
1011
1012 // compute g (d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1013 double g = 0.0;
1014 if (distance2D > 18.0)
1015 {
1016 g = 5.0 / 4.0 * pow(distance2D / 100.0, 3) * exp(-distance2D / 150.0);
1017 }
1018
1019 // compute C (hUt, d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1020 double c = 0.0;
1021 if (hUt >= 13.0)
1022 {
1023 c = pow((hUt - 13.0) / 10.0, 1.5) * g;
1024 }
1025
1026 // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1027 double prob = 1.0 / (1.0 + c);
1028 double hE = 0.0;
1029 if (m_uniformVar->GetValue() < prob)
1030 {
1031 hE = 1.0;
1032 }
1033 else
1034 {
1035 int random = m_uniformVar->GetInteger(12, std::max(12, (int)(hUt - 1.5)));
1036 hE = (double)floor(random / 3.0) * 3.0;
1037 }
1038
1039 // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1040 double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
1041
1042 return distanceBp;
1043}
1044
1045double
1047{
1048 NS_LOG_FUNCTION(this);
1049
1050 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
1051
1052 // check if hBS and hUT are within the validity range
1053 if (hUt < 1.5 || hUt > 22.5)
1054 {
1055 NS_ABORT_MSG_IF(m_enforceRanges, "Uma UT height out of range");
1057 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
1058 }
1059
1060 if (hBs != 25.0)
1061 {
1062 NS_ABORT_MSG_IF(m_enforceRanges, "Uma BS height out of range");
1063 NS_LOG_WARN("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
1064 }
1065
1066 // NOTE The model is intended to be used for BS-UT links, however we may need to
1067 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1068 // interference. In order to apply the model, we need to retrieve the values of
1069 // hBS and hUT, but in these cases one of the two falls outside the validity
1070 // range and the warning message is printed (hBS for the UT-UT case and hUT
1071 // for the BS-BS case).
1072
1073 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
1074 double distanceBp = GetBpDistance(hUt, hBs, distance2D);
1075 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
1076
1077 // check if the distance is outside the validity range
1078 if (distance2D < 10.0 || distance2D > 5.0e3)
1079 {
1080 NS_ABORT_MSG_IF(m_enforceRanges, "Uma 2D distance out of range");
1081 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1082 "accurate");
1083 }
1084
1085 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1086 double loss = 0;
1087 if (distance2D <= distanceBp)
1088 {
1089 // use PL1
1090 loss = 28.0 + 22.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1091 }
1092 else
1093 {
1094 // use PL2
1095 loss = 28.0 + 40.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) -
1096 9.0 * log10(pow(distanceBp, 2) + pow(hBs - hUt, 2));
1097 }
1098
1099 NS_LOG_DEBUG("Loss " << loss);
1100
1101 return loss;
1102}
1103
1104double
1106{
1107 // distance2dIn is minimum of two independently generated uniformly distributed variables
1108 // between 0 and 25 m for UMa and UMi-Street Canyon. 2D−in d shall be UT-specifically generated.
1109 return std::min(m_randomO2iVar1->GetValue(0, 25), m_randomO2iVar2->GetValue(0, 25));
1110}
1111
1112double
1114{
1115 NS_LOG_FUNCTION(this);
1116
1117 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
1118
1119 // check if hBS and hUT are within the validity range
1120 if (hUt < 1.5 || hUt > 22.5)
1121 {
1122 NS_ABORT_MSG_IF(m_enforceRanges, "Uma UT height out of range");
1124 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
1125 }
1126
1127 if (hBs != 25.0)
1128 {
1129 NS_ABORT_MSG_IF(m_enforceRanges, "Uma BS height out of range");
1130 NS_LOG_WARN("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
1131 }
1132
1133 // NOTE The model is intended to be used for BS-UT links, however we may need to
1134 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1135 // interference. In order to apply the model, we need to retrieve the values of
1136 // hBS and hUT, but in these cases one of the two falls outside the validity
1137 // range and the warning message is printed (hBS for the UT-UT case and hUT
1138 // for the BS-BS case).
1139
1140 // check if the distance is outside the validity range
1141 if (distance2D < 10.0 || distance2D > 5.0e3)
1142 {
1143 NS_ABORT_MSG_IF(m_enforceRanges, "Uma 2D distance out of range");
1144 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1145 "accurate");
1146 }
1147
1148 // compute the pathloss
1149 double plNlos =
1150 13.54 + 39.08 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) - 0.6 * (hUt - 1.5);
1151 double loss = std::max(GetLossLos(a, b), plNlos);
1152 NS_LOG_DEBUG("Loss " << loss);
1153
1154 return loss;
1155}
1156
1157double
1159 Ptr<MobilityModel> /* b */,
1161{
1162 NS_LOG_FUNCTION(this);
1163 double shadowingStd;
1164
1166 {
1167 shadowingStd = 4.0;
1168 }
1170 {
1171 shadowingStd = 6.0;
1172 }
1173 else
1174 {
1175 NS_FATAL_ERROR("Unknown channel condition");
1176 }
1177
1178 return shadowingStd;
1179}
1180
1181double
1184{
1185 NS_LOG_FUNCTION(this);
1186 double correlationDistance;
1187
1188 // See 3GPP TR 38.901, Table 7.5-6
1190 {
1191 correlationDistance = 37;
1192 }
1194 {
1195 correlationDistance = 50;
1196 }
1197 else
1198 {
1199 NS_FATAL_ERROR("Unknown channel condition");
1200 }
1201
1202 return correlationDistance;
1203}
1204
1205int64_t
1207{
1208 NS_LOG_FUNCTION(this);
1209
1210 m_normRandomVariable->SetStream(stream);
1211 m_uniformVar->SetStream(stream + 1);
1212 return 2;
1213}
1214
1215// ------------------------------------------------------------------------- //
1216
1218
1219TypeId
1221{
1222 static TypeId tid = TypeId("ns3::ThreeGppUmiStreetCanyonPropagationLossModel")
1224 .SetGroupName("Propagation")
1226 return tid;
1227}
1228
1231{
1232 NS_LOG_FUNCTION(this);
1233
1234 // set a default channel condition model
1235 m_channelConditionModel = CreateObject<ThreeGppUmiStreetCanyonChannelConditionModel>();
1236}
1237
1239{
1240 NS_LOG_FUNCTION(this);
1241}
1242
1243double
1245 double hBs,
1246 double /* distance2D */) const
1247{
1248 NS_LOG_FUNCTION(this);
1249
1250 // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1251 double hE = 1.0;
1252
1253 // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1254 double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
1255
1256 return distanceBp;
1257}
1258
1259double
1261{
1262 // distance2dIn is minimum of two independently generated uniformly distributed variables
1263 // between 0 and 25 m for UMa and UMi-Street Canyon. 2D−in d shall be UT-specifically generated.
1264 return std::min(m_randomO2iVar1->GetValue(0, 25), m_randomO2iVar2->GetValue(0, 25));
1265}
1266
1267double
1269 Ptr<MobilityModel> b) const
1270{
1271 NS_LOG_FUNCTION(this);
1272
1273 double distance2D = Calculate2dDistance(a->GetPosition(), b->GetPosition());
1274 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1275 auto [hBs, hUt] = GetBsUtHeightsUmiStreetCanyon(a->GetPosition().z, b->GetPosition().z);
1276
1277 // check if hBS and hUT are within the validity range
1278 if (hUt < 1.5 || hUt >= 10.0)
1279 {
1280 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon UT height out of range");
1282 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). "
1283 "We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
1284 }
1285
1286 if (hBs != 10.0)
1287 {
1288 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon BS height out of range");
1289 NS_LOG_WARN("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
1290 }
1291
1292 // NOTE The model is intended to be used for BS-UT links, however we may need to
1293 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1294 // interference. In order to apply the model, we need to retrieve the values of
1295 // hBS and hUT, but in these cases one of the two falls outside the validity
1296 // range and the warning message is printed (hBS for the UT-UT case and hUT
1297 // for the BS-BS case).
1298
1299 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
1300 double distanceBp = GetBpDistance(hUt, hBs, distance2D);
1301 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
1302
1303 // check if the distance is outside the validity range
1304 if (distance2D < 10.0 || distance2D > 5.0e3)
1305 {
1306 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon 2D distance out of range");
1307 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1308 "accurate");
1309 }
1310
1311 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1312 double loss = 0;
1313 if (distance2D <= distanceBp)
1314 {
1315 // use PL1
1316 loss = 32.4 + 21.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1317 }
1318 else
1319 {
1320 // use PL2
1321 loss = 32.4 + 40.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) -
1322 9.5 * log10(pow(distanceBp, 2) + pow(hBs - hUt, 2));
1323 }
1324
1325 NS_LOG_DEBUG("Loss " << loss);
1326
1327 return loss;
1328}
1329
1330double
1332 Ptr<MobilityModel> b) const
1333{
1334 NS_LOG_FUNCTION(this);
1335
1336 double distance2D = Calculate2dDistance(a->GetPosition(), b->GetPosition());
1337 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1338 auto [hBs, hUt] = GetBsUtHeightsUmiStreetCanyon(a->GetPosition().z, b->GetPosition().z);
1339
1340 // check if hBS and hUT are within the validity range
1341 if (hUt < 1.5 || hUt >= 10.0)
1342 {
1343 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon UT height out of range");
1345 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). "
1346 "We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
1347 }
1348
1349 if (hBs != 10.0)
1350 {
1351 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon BS height out of range");
1352 NS_LOG_WARN("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
1353 }
1354
1355 // NOTE The model is intended to be used for BS-UT links, however we may need to
1356 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1357 // interference. In order to apply the model, we need to retrieve the values of
1358 // hBS and hUT, but in these cases one of the two falls outside the validity
1359 // range and the warning message is printed (hBS for the UT-UT case and hUT
1360 // for the BS-BS case).
1361
1362 // check if the distance is outside the validity range
1363 if (distance2D < 10.0 || distance2D > 5.0e3)
1364 {
1365 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon 2D distance out of range");
1366 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1367 "accurate");
1368 }
1369
1370 // compute the pathloss
1371 double plNlos =
1372 22.4 + 35.3 * log10(distance3D) + 21.3 * log10(m_frequency / 1e9) - 0.3 * (hUt - 1.5);
1373 double loss = std::max(GetLossLos(a, b), plNlos);
1374 NS_LOG_DEBUG("Loss " << loss);
1375
1376 return loss;
1377}
1378
1379double
1381 Ptr<MobilityModel> /* a */,
1382 Ptr<MobilityModel> /* b */,
1384{
1385 NS_LOG_FUNCTION(this);
1386 double shadowingStd;
1387
1389 {
1390 shadowingStd = 4.0;
1391 }
1393 {
1394 shadowingStd = 7.82;
1395 }
1396 else
1397 {
1398 NS_FATAL_ERROR("Unknown channel condition");
1399 }
1400
1401 return shadowingStd;
1402}
1403
1404double
1407{
1408 NS_LOG_FUNCTION(this);
1409 double correlationDistance;
1410
1411 // See 3GPP TR 38.901, Table 7.5-6
1413 {
1414 correlationDistance = 10;
1415 }
1417 {
1418 correlationDistance = 13;
1419 }
1420 else
1421 {
1422 NS_FATAL_ERROR("Unknown channel condition");
1423 }
1424
1425 return correlationDistance;
1426}
1427
1428// ------------------------------------------------------------------------- //
1429
1431
1432TypeId
1434{
1435 static TypeId tid = TypeId("ns3::ThreeGppIndoorOfficePropagationLossModel")
1437 .SetGroupName("Propagation")
1439 return tid;
1440}
1441
1444{
1445 NS_LOG_FUNCTION(this);
1446
1447 // set a default channel condition model
1448 m_channelConditionModel = CreateObject<ThreeGppIndoorOpenOfficeChannelConditionModel>();
1449}
1450
1452{
1453 NS_LOG_FUNCTION(this);
1454}
1455
1456double
1458{
1459 return 0;
1460}
1461
1462double
1464 Ptr<MobilityModel> b) const
1465{
1466 NS_LOG_FUNCTION(this);
1467
1468 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1469
1470 // check if the distance is outside the validity range
1471 if (distance3D < 1.0 || distance3D > 150.0)
1472 {
1473 NS_ABORT_MSG_IF(m_enforceRanges, "IndoorOffice 3D distance out of range");
1474 NS_LOG_WARN("The 3D distance is outside the validity range, the pathloss value may not be "
1475 "accurate");
1476 }
1477
1478 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1479 double loss = 32.4 + 17.3 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1480
1481 NS_LOG_DEBUG("Loss " << loss);
1482
1483 return loss;
1484}
1485
1486double
1488 Ptr<MobilityModel> b) const
1489{
1490 NS_LOG_FUNCTION(this);
1491
1492 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1493
1494 // check if the distance is outside the validity range
1495 if (distance3D < 1.0 || distance3D > 150.0)
1496 {
1497 NS_ABORT_MSG_IF(m_enforceRanges, "IndoorOffice 3D distance out of range");
1498 NS_LOG_WARN("The 3D distance is outside the validity range, the pathloss value may not be "
1499 "accurate");
1500 }
1501
1502 // compute the pathloss
1503 double plNlos = 17.3 + 38.3 * log10(distance3D) + 24.9 * log10(m_frequency / 1e9);
1504 double loss = std::max(GetLossLos(a, b), plNlos);
1505
1506 NS_LOG_DEBUG("Loss " << loss);
1507
1508 return loss;
1509}
1510
1511double
1513 Ptr<MobilityModel> /* a */,
1514 Ptr<MobilityModel> /* b */,
1516{
1517 NS_LOG_FUNCTION(this);
1518 double shadowingStd;
1519
1521 {
1522 shadowingStd = 3.0;
1523 }
1525 {
1526 shadowingStd = 8.03;
1527 }
1528 else
1529 {
1530 NS_FATAL_ERROR("Unknown channel condition");
1531 }
1532
1533 return shadowingStd;
1534}
1535
1536double
1539{
1540 NS_LOG_FUNCTION(this);
1541
1542 // See 3GPP TR 38.901, Table 7.5-6
1543 double correlationDistance;
1544
1546 {
1547 correlationDistance = 10;
1548 }
1550 {
1551 correlationDistance = 6;
1552 }
1553 else
1554 {
1555 NS_FATAL_ERROR("Unknown channel condition");
1556 }
1557
1558 return correlationDistance;
1559}
1560
1562
1563TypeId
1565{
1566 static TypeId tid = TypeId("ns3::ThreeGppNTNDenseUrbanPropagationLossModel")
1568 .SetGroupName("Propagation")
1570 return tid;
1571}
1572
1575 m_SFCL_DenseUrban(&SFCL_DenseUrban)
1576{
1577 NS_LOG_FUNCTION(this);
1578 m_channelConditionModel = CreateObject<ThreeGppNTNDenseUrbanChannelConditionModel>();
1579}
1580
1582{
1583 NS_LOG_FUNCTION(this);
1584}
1585
1586double
1588{
1589 abort();
1590}
1591
1592double
1594 Ptr<MobilityModel> b) const
1595{
1596 NS_LOG_FUNCTION(this);
1597 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1598 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1599
1600 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1601 auto [elevAngle, elevAngleQuantized] =
1603
1604 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1605 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1606
1607 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1608 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1609
1610 // Apply Ionospheric plus Tropospheric Scintillation Loss
1611 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1612
1613 NS_LOG_DEBUG("Loss " << loss);
1614 return loss;
1615}
1616
1617double
1619 Ptr<MobilityModel> b) const
1620{
1621 NS_LOG_FUNCTION(this);
1622 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1623 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1624
1625 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1626 auto [elevAngle, elevAngleQuantized] =
1628
1629 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1630 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1631
1632 // Apply Clutter Loss
1633 loss += ComputeClutterLoss(m_frequency, m_SFCL_DenseUrban, elevAngleQuantized);
1634
1635 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1636 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1637
1638 // Apply Ionospheric plus Tropospheric Scintillation Loss
1639 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1640
1641 NS_LOG_DEBUG("Loss " << loss);
1642 return loss;
1643}
1644
1645double
1650{
1651 NS_LOG_FUNCTION(this);
1652 double shadowingStd;
1653
1654 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
1655 auto [elevAngle, elevAngleQuantized] =
1657
1658 // Assign Shadowing Standard Deviation according to table 6.6.2-1
1659 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
1660 {
1661 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
1662 }
1663 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
1664 {
1665 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
1666 }
1667 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
1668 {
1669 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
1670 }
1671 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
1672 {
1673 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
1674 }
1675 else
1676 {
1677 NS_FATAL_ERROR("Unknown channel condition");
1678 }
1679
1680 return shadowingStd;
1681}
1682
1683double
1686{
1687 NS_LOG_FUNCTION(this);
1688 double correlationDistance;
1689
1690 // See 3GPP TR 38.811, Table 6.7.2-1a/b and Table 6.7.2-2a/b
1692 {
1693 correlationDistance = 37;
1694 }
1696 {
1697 correlationDistance = 50;
1698 }
1699 else
1700 {
1701 NS_FATAL_ERROR("Unknown channel condition");
1702 }
1703
1704 return correlationDistance;
1705}
1706
1707// ------------------------------------------------------------------------- //
1708
1710
1711TypeId
1713{
1714 static TypeId tid = TypeId("ns3::ThreeGppNTNUrbanPropagationLossModel")
1716 .SetGroupName("Propagation")
1717 .AddConstructor<ThreeGppNTNUrbanPropagationLossModel>();
1718 return tid;
1719}
1720
1723 m_SFCL_Urban(&SFCL_Urban)
1724{
1725 NS_LOG_FUNCTION(this);
1726 m_channelConditionModel = CreateObject<ThreeGppNTNUrbanChannelConditionModel>();
1727}
1728
1730{
1731 NS_LOG_FUNCTION(this);
1732}
1733
1734double
1736{
1737 abort();
1738}
1739
1740double
1742{
1743 NS_LOG_FUNCTION(this);
1744 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1745 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1746
1747 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1748 auto [elevAngle, elevAngleQuantized] =
1750
1751 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1752 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1753
1754 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1755 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1756
1757 // Apply Ionospheric plus Tropospheric Scintillation Loss
1758 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1759
1760 NS_LOG_DEBUG("Loss " << loss);
1761 return loss;
1762}
1763
1764double
1766{
1767 NS_LOG_FUNCTION(this);
1768 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1769 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1770
1771 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1772 auto [elevAngle, elevAngleQuantized] =
1774
1775 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1776 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1777
1778 // Apply Clutter Loss
1779 loss += ComputeClutterLoss(m_frequency, m_SFCL_Urban, elevAngleQuantized);
1780
1781 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1782 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1783
1784 // Apply Ionospheric plus Tropospheric Scintillation Loss
1785 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1786
1787 NS_LOG_DEBUG("Loss " << loss);
1788 return loss;
1789}
1790
1791double
1796{
1797 NS_LOG_FUNCTION(this);
1798 double shadowingStd;
1799
1800 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
1801 auto [elevAngle, elevAngleQuantized] =
1803
1804 // Assign Shadowing Standard Deviation according to table 6.6.2-1
1805 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
1806 {
1807 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
1808 }
1809 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
1810 {
1811 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
1812 }
1813 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
1814 {
1815 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
1816 }
1817 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
1818 {
1819 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
1820 }
1821 else
1822 {
1823 NS_FATAL_ERROR("Unknown channel condition");
1824 }
1825
1826 return shadowingStd;
1827}
1828
1829double
1832{
1833 NS_LOG_FUNCTION(this);
1834 double correlationDistance;
1835
1836 // See 3GPP TR 38.811, Table 6.7.2-3a/b and Table 6.7.2-3a/b
1838 {
1839 correlationDistance = 37;
1840 }
1842 {
1843 correlationDistance = 50;
1844 }
1845 else
1846 {
1847 NS_FATAL_ERROR("Unknown channel condition");
1848 }
1849
1850 return correlationDistance;
1851}
1852
1853// ------------------------------------------------------------------------- //
1854
1856
1857TypeId
1859{
1860 static TypeId tid = TypeId("ns3::ThreeGppNTNSuburbanPropagationLossModel")
1862 .SetGroupName("Propagation")
1863 .AddConstructor<ThreeGppNTNSuburbanPropagationLossModel>();
1864 return tid;
1865}
1866
1869 m_SFCL_SuburbanRural(&SFCL_SuburbanRural)
1870{
1871 NS_LOG_FUNCTION(this);
1872 m_channelConditionModel = CreateObject<ThreeGppNTNSuburbanChannelConditionModel>();
1873}
1874
1876{
1877 NS_LOG_FUNCTION(this);
1878}
1879
1880double
1882{
1883 abort();
1884}
1885
1886double
1888 Ptr<MobilityModel> b) const
1889{
1890 NS_LOG_FUNCTION(this);
1891 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1892 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1893
1894 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1895 auto [elevAngle, elevAngleQuantized] =
1897
1898 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1899 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1900
1901 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1902 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1903
1904 // Apply Ionospheric plus Tropospheric Scintillation Loss
1905 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1906
1907 NS_LOG_DEBUG("Loss " << loss);
1908
1909 return loss;
1910}
1911
1912double
1914 Ptr<MobilityModel> b) const
1915{
1916 NS_LOG_FUNCTION(this);
1917 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1918 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1919
1920 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1921 auto [elevAngle, elevAngleQuantized] =
1923
1924 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1925 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1926
1927 // Apply Clutter Loss
1928 loss += ComputeClutterLoss(m_frequency, m_SFCL_SuburbanRural, elevAngleQuantized);
1929
1930 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1931 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1932
1933 // Apply Ionospheric plus Tropospheric Scintillation Loss
1934 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1935
1936 NS_LOG_DEBUG("Loss " << loss);
1937 return loss;
1938}
1939
1940double
1945{
1946 NS_LOG_FUNCTION(this);
1947 double shadowingStd;
1948
1949 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
1950 auto [elevAngle, elevAngleQuantized] =
1952
1953 // Assign Shadowing Standard Deviation according to table 6.6.2-1
1954 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
1955 {
1956 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
1957 }
1958 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
1959 {
1960 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
1961 }
1962 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
1963 {
1964 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
1965 }
1966 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
1967 {
1968 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
1969 }
1970 else
1971 {
1972 NS_FATAL_ERROR("Unknown channel condition");
1973 }
1974
1975 return shadowingStd;
1976}
1977
1978double
1981{
1982 NS_LOG_FUNCTION(this);
1983 double correlationDistance;
1984
1985 // See 3GPP TR 38.811, Table 6.7.2-5a/b and Table 6.7.2-6a/b
1987 {
1988 correlationDistance = 37;
1989 }
1991 {
1992 correlationDistance = 50;
1993 }
1994 else
1995 {
1996 NS_FATAL_ERROR("Unknown channel condition");
1997 }
1998
1999 return correlationDistance;
2000}
2001
2002// ------------------------------------------------------------------------- //
2003
2005
2006TypeId
2008{
2009 static TypeId tid = TypeId("ns3::ThreeGppNTNRuralPropagationLossModel")
2011 .SetGroupName("Propagation")
2012 .AddConstructor<ThreeGppNTNRuralPropagationLossModel>();
2013 return tid;
2014}
2015
2018 m_SFCL_SuburbanRural(&SFCL_SuburbanRural)
2019{
2020 NS_LOG_FUNCTION(this);
2021 m_channelConditionModel = CreateObject<ThreeGppNTNRuralChannelConditionModel>();
2022}
2023
2025{
2026 NS_LOG_FUNCTION(this);
2027}
2028
2029double
2031{
2032 abort();
2033}
2034
2035double
2037{
2038 NS_LOG_FUNCTION(this);
2039 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2040 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2041
2042 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2043 auto [elevAngle, elevAngleQuantized] =
2045
2046 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2047 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2048
2049 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2050 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2051
2052 // Apply Ionospheric plus Tropospheric Scintillation Loss
2053 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2054
2055 NS_LOG_DEBUG("Loss " << loss);
2056 return loss;
2057}
2058
2059double
2061{
2062 NS_LOG_FUNCTION(this);
2063 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2064 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2065
2066 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2067 auto [elevAngle, elevAngleQuantized] =
2069
2070 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2071 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2072
2073 // Apply Clutter Loss
2074 loss += ComputeClutterLoss(m_frequency, m_SFCL_SuburbanRural, elevAngleQuantized);
2075
2076 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2077 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2078
2079 // Apply Ionospheric plus Tropospheric Scintillation Loss
2080 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2081
2082 NS_LOG_DEBUG("Loss " << loss);
2083 return loss;
2084}
2085
2086double
2091{
2092 NS_LOG_FUNCTION(this);
2093 double shadowingStd;
2094
2095 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
2096 auto [elevAngle, elevAngleQuantized] =
2098
2099 // Assign Shadowing Standard Deviation according to table 6.6.2-1
2100 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
2101 {
2102 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
2103 }
2104 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
2105 {
2106 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
2107 }
2108 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
2109 {
2110 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
2111 }
2112 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
2113 {
2114 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
2115 }
2116 else
2117 {
2118 NS_FATAL_ERROR("Unknown channel condition");
2119 }
2120
2121 return shadowingStd;
2122}
2123
2124double
2127{
2128 NS_LOG_FUNCTION(this);
2129 double correlationDistance;
2130
2131 // See 3GPP TR 38.811, Table 6.7.2-7a/b and Table 6.7.2-8a/b
2133 {
2134 correlationDistance = 37;
2135 }
2137 {
2138 correlationDistance = 120;
2139 }
2140 else
2141 {
2142 NS_FATAL_ERROR("Unknown channel condition");
2143 }
2144
2145 return correlationDistance;
2146}
2147
2148} // namespace ns3
@ 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:42
A network Node.
Definition: node.h:57
uint32_t GetId() const
Definition: node.cc:117
AttributeValue implementation for Pointer.
Definition: pointer.h:48
Models the propagation loss through a transmission medium.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
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 ???? for the NTN Dense Urban scenario.
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 ???? for the NTN Rural scenario.
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 ???? for the NTN Suburban scenario.
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 ???? for the NTN Urban 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.
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.
Base class for the 3GPP propagation models.
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 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.
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...
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.
void SetFrequency(double f)
Set the central frequency of the model.
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....
static Vector GetVectorDifference(Ptr< MobilityModel > a, Ptr< MobilityModel > b)
Get the difference between the node position.
bool m_buildingPenLossesEnabled
enable/disable building penetration losses
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 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 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:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
uint32_t GetInteger(uint32_t min, uint32_t max)
Get the next random value drawn from the distribution.
a 2d vector
Definition: vector.h:207
double GetLength() const
Compute the length (magnitude) of the vector.
Definition: vector.cc:88
#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:86
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:259
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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:261
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
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.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
double CalculateDistance(const Vector3D &a, const Vector3D &b)
Definition: vector.cc:109
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:81
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43