A Discrete-Event Network Simulator
API
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 
21 #include "ns3/boolean.h"
22 #include "ns3/channel-condition-model.h"
23 #include "ns3/double.h"
24 #include "ns3/log.h"
25 #include "ns3/mobility-model.h"
26 #include "ns3/node.h"
27 #include "ns3/pointer.h"
28 #include "ns3/simulator.h"
29 
30 #include <cmath>
31 
32 namespace ns3
33 {
34 
35 NS_LOG_COMPONENT_DEFINE("ThreeGppPropagationLossModel");
36 
37 static const double M_C = 3.0e8;
38 
39 // ------------------------------------------------------------------------- //
40 
42 
43 TypeId
45 {
46  static TypeId tid =
47  TypeId("ns3::ThreeGppPropagationLossModel")
49  .SetGroupName("Propagation")
50  .AddAttribute("Frequency",
51  "The centre frequency in Hz.",
52  DoubleValue(500.0e6),
55  MakeDoubleChecker<double>())
56  .AddAttribute("ShadowingEnabled",
57  "Enable/disable shadowing.",
58  BooleanValue(true),
61  .AddAttribute(
62  "ChannelConditionModel",
63  "Pointer to the channel condition model.",
64  PointerValue(),
67  MakePointerChecker<ChannelConditionModel>())
68  .AddAttribute("EnforceParameterRanges",
69  "Whether to strictly enforce TR38.901 applicability ranges",
70  BooleanValue(false),
73  .AddAttribute(
74  "BuildingPenetrationLossesEnabled",
75  "Enable/disable Building Penetration Losses.",
76  BooleanValue(true),
79  return tid;
80 }
81 
84 {
85  NS_LOG_FUNCTION(this);
86 
87  // initialize the normal random variables
88  m_normRandomVariable = CreateObject<NormalRandomVariable>();
89  m_normRandomVariable->SetAttribute("Mean", DoubleValue(0));
90  m_normRandomVariable->SetAttribute("Variance", DoubleValue(1));
91 
92  m_randomO2iVar1 = CreateObject<UniformRandomVariable>();
93  m_randomO2iVar2 = CreateObject<UniformRandomVariable>();
94 
95  m_normalO2iLowLossVar = CreateObject<NormalRandomVariable>();
96  m_normalO2iLowLossVar->SetAttribute("Mean", DoubleValue(0));
97  m_normalO2iLowLossVar->SetAttribute("Variance", DoubleValue(4.4));
98 
99  m_normalO2iHighLossVar = CreateObject<NormalRandomVariable>();
100  m_normalO2iHighLossVar->SetAttribute("Mean", DoubleValue(0));
101  m_normalO2iHighLossVar->SetAttribute("Variance", DoubleValue(6.5));
102 }
103 
105 {
106  NS_LOG_FUNCTION(this);
107 }
108 
109 void
111 {
112  m_channelConditionModel->Dispose();
113  m_channelConditionModel = nullptr;
114  m_shadowingMap.clear();
115 }
116 
117 void
119 {
120  NS_LOG_FUNCTION(this);
121  m_channelConditionModel = model;
122 }
123 
126 {
127  NS_LOG_FUNCTION(this);
129 }
130 
131 void
133 {
134  NS_LOG_FUNCTION(this);
135  NS_ASSERT_MSG(f >= 500.0e6 && f <= 100.0e9,
136  "Frequency should be between 0.5 and 100 GHz but is " << f);
137  m_frequency = f;
138 }
139 
140 double
142 {
143  NS_LOG_FUNCTION(this);
144  return m_frequency;
145 }
146 
147 double
150  Ptr<MobilityModel> b) const
151 {
152  NS_LOG_FUNCTION(this);
153 
154  // check if the model is initialized
155  NS_ASSERT_MSG(m_frequency != 0.0, "First set the centre frequency");
156 
157  // retrieve the channel condition
158  NS_ASSERT_MSG(m_channelConditionModel, "First set the channel condition model");
159  Ptr<ChannelCondition> cond = m_channelConditionModel->GetChannelCondition(a, b);
160 
161  // compute the 2D distance between a and b
162  double distance2d = Calculate2dDistance(a->GetPosition(), b->GetPosition());
163 
164  // compute the 3D distance between a and b
165  double distance3d = CalculateDistance(a->GetPosition(), b->GetPosition());
166 
167  // compute hUT and hBS
168  std::pair<double, double> heights = GetUtAndBsHeights(a->GetPosition().z, b->GetPosition().z);
169 
170  double rxPow = txPowerDbm;
171  rxPow -= GetLoss(cond, distance2d, distance3d, heights.first, heights.second);
172 
173  if (m_shadowingEnabled)
174  {
175  rxPow -= GetShadowing(a, b, cond->GetLosCondition());
176  }
177 
178  // get o2i losses
179  if (cond->GetO2iCondition() == ChannelCondition::O2iConditionValue::O2I &&
181  {
182  if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::LOW)
183  {
184  rxPow -= GetO2iLowPenetrationLoss(a, b, cond->GetLosCondition());
185  }
186  else if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::HIGH)
187  {
188  rxPow -= GetO2iHighPenetrationLoss(a, b, cond->GetLosCondition());
189  }
190  else
191  {
192  NS_ABORT_MSG("If we have set the O2I condition, we shouldn't be here");
193  }
194  }
195 
196  return rxPow;
197 }
198 
199 double
201  double distance2d,
202  double distance3d,
203  double hUt,
204  double hBs) const
205 {
206  NS_LOG_FUNCTION(this);
207 
208  double loss = 0;
209  if (cond->GetLosCondition() == ChannelCondition::LosConditionValue::LOS)
210  {
211  loss = GetLossLos(distance2d, distance3d, hUt, hBs);
212  }
213  else if (cond->GetLosCondition() == ChannelCondition::LosConditionValue::NLOSv)
214  {
215  loss = GetLossNlosv(distance2d, distance3d, hUt, hBs);
216  }
217  else if (cond->GetLosCondition() == ChannelCondition::LosConditionValue::NLOS)
218  {
219  loss = GetLossNlos(distance2d, distance3d, hUt, hBs);
220  }
221  else
222  {
223  NS_FATAL_ERROR("Unknown channel condition");
224  }
225 
226  return loss;
227 }
228 
229 double
234 {
235  NS_LOG_FUNCTION(this);
236 
237  double o2iLossValue = 0;
238  double lowLossTw = 0;
239  double lossIn = 0;
240  double lowlossNormalVariate = 0;
241  double lGlass = 0;
242  double lConcrete = 0;
243 
244  // compute the channel key
245  uint32_t key = GetKey(a, b);
246 
247  bool notFound = false; // indicates if the o2iLoss value has not been computed yet
248  bool newCondition = false; // indicates if the channel condition has changed
249 
250  auto it = m_o2iLossMap.end(); // the o2iLoss map iterator
251  if (m_o2iLossMap.find(key) != m_o2iLossMap.end())
252  {
253  // found the o2iLoss value in the map
254  it = m_o2iLossMap.find(key);
255  newCondition = (it->second.m_condition != cond); // true if the condition changed
256  }
257  else
258  {
259  notFound = true;
260  // add a new entry in the map and update the iterator
261  O2iLossMapItem newItem;
262  it = m_o2iLossMap.insert(it, std::make_pair(key, newItem));
263  }
264 
265  if (notFound || newCondition)
266  {
267  // distance2dIn is minimum of two independently generated uniformly distributed
268  // variables between 0 and 25 m for UMa and UMi-Street Canyon, and between 0 and
269  // 10 m for RMa. 2D−in d shall be UT-specifically generated.
270  double distance2dIn = GetO2iDistance2dIn();
271 
272  // calculate material penetration losses, see TR 38.901 Table 7.4.3-1
273  lGlass = 2 + 0.2 * m_frequency / 1e9; // m_frequency is operation frequency in Hz
274  lConcrete = 5 + 4 * m_frequency / 1e9;
275 
276  lowLossTw =
277  5 - 10 * log10(0.3 * std::pow(10, -lGlass / 10) + 0.7 * std::pow(10, -lConcrete / 10));
278 
279  // calculate indoor loss
280  lossIn = 0.5 * distance2dIn;
281 
282  // calculate low loss standard deviation
283  lowlossNormalVariate = m_normalO2iLowLossVar->GetValue();
284 
285  o2iLossValue = lowLossTw + lossIn + lowlossNormalVariate;
286  }
287  else
288  {
289  o2iLossValue = it->second.m_o2iLoss;
290  }
291 
292  // update the entry in the map
293  it->second.m_o2iLoss = o2iLossValue;
294  it->second.m_condition = cond;
295 
296  return o2iLossValue;
297 }
298 
299 double
304 {
305  NS_LOG_FUNCTION(this);
306 
307  double o2iLossValue = 0;
308  double highLossTw = 0;
309  double lossIn = 0;
310  double highlossNormalVariate = 0;
311  double lIIRGlass = 0;
312  double lConcrete = 0;
313 
314  // compute the channel key
315  uint32_t key = GetKey(a, b);
316 
317  bool notFound = false; // indicates if the o2iLoss value has not been computed yet
318  bool newCondition = false; // indicates if the channel condition has changed
319 
320  auto it = m_o2iLossMap.end(); // the o2iLoss map iterator
321  if (m_o2iLossMap.find(key) != m_o2iLossMap.end())
322  {
323  // found the o2iLoss value in the map
324  it = m_o2iLossMap.find(key);
325  newCondition = (it->second.m_condition != cond); // true if the condition changed
326  }
327  else
328  {
329  notFound = true;
330  // add a new entry in the map and update the iterator
331  O2iLossMapItem newItem;
332  it = m_o2iLossMap.insert(it, std::make_pair(key, newItem));
333  }
334 
335  if (notFound || newCondition)
336  {
337  // generate a new independent realization
338 
339  // distance2dIn is minimum of two independently generated uniformly distributed
340  // variables between 0 and 25 m for UMa and UMi-Street Canyon, and between 0 and
341  // 10 m for RMa. 2D−in d shall be UT-specifically generated.
342  double distance2dIn = GetO2iDistance2dIn();
343 
344  // calculate material penetration losses, see TR 38.901 Table 7.4.3-1
345  lIIRGlass = 23 + 0.3 * m_frequency / 1e9;
346  lConcrete = 5 + 4 * m_frequency / 1e9;
347 
348  highLossTw = 5 - 10 * log10(0.7 * std::pow(10, -lIIRGlass / 10) +
349  0.3 * std::pow(10, -lConcrete / 10));
350 
351  // calculate indoor loss
352  lossIn = 0.5 * distance2dIn;
353 
354  // calculate low loss standard deviation
355  highlossNormalVariate = m_normalO2iHighLossVar->GetValue();
356 
357  o2iLossValue = highLossTw + lossIn + highlossNormalVariate;
358  }
359  else
360  {
361  o2iLossValue = it->second.m_o2iLoss;
362  }
363 
364  // update the entry in the map
365  it->second.m_o2iLoss = o2iLossValue;
366  it->second.m_condition = cond;
367 
368  return o2iLossValue;
369 }
370 
371 double
373  double distance3D,
374  double hUt,
375  double hBs) const
376 {
377  NS_LOG_FUNCTION(this);
378  NS_FATAL_ERROR("Unsupported channel condition (NLOSv)");
379  return 0;
380 }
381 
382 double
386 {
387  NS_LOG_FUNCTION(this);
388 
389  double shadowingValue;
390 
391  // compute the channel key
392  uint32_t key = GetKey(a, b);
393 
394  bool notFound = false; // indicates if the shadowing value has not been computed yet
395  bool newCondition = false; // indicates if the channel condition has changed
396  Vector newDistance; // the distance vector, that is not a distance but a difference
397  auto it = m_shadowingMap.end(); // the shadowing map iterator
398  if (m_shadowingMap.find(key) != m_shadowingMap.end())
399  {
400  // found the shadowing value in the map
401  it = m_shadowingMap.find(key);
402  newDistance = GetVectorDifference(a, b);
403  newCondition = (it->second.m_condition != cond); // true if the condition changed
404  }
405  else
406  {
407  notFound = true;
408 
409  // add a new entry in the map and update the iterator
410  ShadowingMapItem newItem;
411  it = m_shadowingMap.insert(it, std::make_pair(key, newItem));
412  }
413 
414  if (notFound || newCondition)
415  {
416  // generate a new independent realization
417  shadowingValue = m_normRandomVariable->GetValue() * GetShadowingStd(a, b, cond);
418  }
419  else
420  {
421  // compute a new correlated shadowing loss
422  Vector2D displacement(newDistance.x - it->second.m_distance.x,
423  newDistance.y - it->second.m_distance.y);
424  double R = exp(-1 * displacement.GetLength() / GetShadowingCorrelationDistance(cond));
425  shadowingValue = R * it->second.m_shadowing + sqrt(1 - R * R) *
426  m_normRandomVariable->GetValue() *
427  GetShadowingStd(a, b, cond);
428  }
429 
430  // update the entry in the map
431  it->second.m_shadowing = shadowingValue;
432  it->second.m_distance = newDistance; // Save the (0,0,0) vector in case it's the first time we
433  // are calculating this value
434  it->second.m_condition = cond;
435 
436  return shadowingValue;
437 }
438 
439 std::pair<double, double>
441 {
442  // The default implementation assumes that the tallest node is the BS and the
443  // smallest is the UT.
444  double hUt = std::min(za, zb);
445  double hBs = std::max(za, zb);
446 
447  return std::pair<double, double>(hUt, hBs);
448 }
449 
450 int64_t
452 {
453  NS_LOG_FUNCTION(this);
454 
455  m_normRandomVariable->SetStream(stream);
456  m_randomO2iVar1->SetStream(stream + 1);
457  m_randomO2iVar2->SetStream(stream + 2);
458  m_normalO2iLowLossVar->SetStream(stream + 3);
459  m_normalO2iHighLossVar->SetStream(stream + 4);
460 
461  return 5;
462 }
463 
464 double
466 {
467  double x = a.x - b.x;
468  double y = a.y - b.y;
469  double distance2D = sqrt(x * x + y * y);
470 
471  return distance2D;
472 }
473 
474 uint32_t
476 {
477  // use the nodes ids to obtain an unique key for the channel between a and b
478  // sort the nodes ids so that the key is reciprocal
479  uint32_t x1 = std::min(a->GetObject<Node>()->GetId(), b->GetObject<Node>()->GetId());
480  uint32_t x2 = std::max(a->GetObject<Node>()->GetId(), b->GetObject<Node>()->GetId());
481 
482  // use the cantor function to obtain the key
483  uint32_t key = (((x1 + x2) * (x1 + x2 + 1)) / 2) + x2;
484 
485  return key;
486 }
487 
488 Vector
490 {
491  uint32_t x1 = a->GetObject<Node>()->GetId();
492  uint32_t x2 = b->GetObject<Node>()->GetId();
493 
494  if (x1 < x2)
495  {
496  return b->GetPosition() - a->GetPosition();
497  }
498  else
499  {
500  return a->GetPosition() - b->GetPosition();
501  }
502 }
503 
504 // ------------------------------------------------------------------------- //
505 
507 
508 TypeId
510 {
511  static TypeId tid = TypeId("ns3::ThreeGppRmaPropagationLossModel")
513  .SetGroupName("Propagation")
514  .AddConstructor<ThreeGppRmaPropagationLossModel>()
515  .AddAttribute("AvgBuildingHeight",
516  "The average building height in meters.",
517  DoubleValue(5.0),
519  MakeDoubleChecker<double>(5.0, 50.0))
520  .AddAttribute("AvgStreetWidth",
521  "The average street width in meters.",
522  DoubleValue(20.0),
524  MakeDoubleChecker<double>(5.0, 50.0));
525  return tid;
526 }
527 
530 {
531  NS_LOG_FUNCTION(this);
532 
533  // set a default channel condition model
534  m_channelConditionModel = CreateObject<ThreeGppRmaChannelConditionModel>();
535 }
536 
538 {
539  NS_LOG_FUNCTION(this);
540 }
541 
542 double
544 {
545  // distance2dIn is minimum of two independently generated uniformly distributed variables
546  // between 0 and 10 m for RMa. 2D−in d shall be UT-specifically generated.
547  return std::min(m_randomO2iVar1->GetValue(0, 10), m_randomO2iVar2->GetValue(0, 10));
548 }
549 
550 double
552  double distance3D,
553  double hUt,
554  double hBs) const
555 {
556  NS_LOG_FUNCTION(this);
557  NS_ASSERT_MSG(m_frequency <= 30.0e9,
558  "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
559 
560  // check if hBS and hUT are within the specified validity range
561  if (hUt < 1.0 || hUt > 10.0)
562  {
563  NS_ABORT_MSG_IF(m_enforceRanges, "Rma UT height out of range");
564  NS_LOG_WARN(
565  "The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
566  }
567 
568  if (hBs < 10.0 || hBs > 150.0)
569  {
570  NS_ABORT_MSG_IF(m_enforceRanges, "Rma BS height out of range");
571  NS_LOG_WARN(
572  "The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
573  }
574 
575  // NOTE The model is intended to be used for BS-UT links, however we may need to
576  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
577  // interference. In order to apply the model, we need to retrieve the values of
578  // hBS and hUT, but in these cases one of the two falls outside the validity
579  // range and the warning message is printed (hBS for the UT-UT case and hUT
580  // for the BS-BS case).
581 
582  double distanceBp = GetBpDistance(m_frequency, hBs, hUt);
583  NS_LOG_DEBUG("breakpoint distance " << distanceBp);
585  distanceBp > 0,
586  "Breakpoint distance is zero (divide-by-zero below); are either hBs or hUt = 0?");
587 
588  // check if the distance is outside the validity range
589  if (distance2D < 10.0 || distance2D > 10.0e3)
590  {
591  NS_ABORT_MSG_IF(m_enforceRanges, "Rma distance2D out of range");
592  NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
593  "accurate");
594  }
595 
596  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
597  double loss = 0;
598  if (distance2D <= distanceBp)
599  {
600  // use PL1
601  loss = Pl1(m_frequency, distance3D, m_h, m_w);
602  }
603  else
604  {
605  // use PL2
606  loss = Pl1(m_frequency, distanceBp, m_h, m_w) + 40 * log10(distance3D / distanceBp);
607  }
608 
609  NS_LOG_DEBUG("Loss " << loss);
610 
611  return loss;
612 }
613 
614 double
616  double distance3D,
617  double hUt,
618  double hBs) const
619 {
620  NS_LOG_FUNCTION(this);
621  NS_ASSERT_MSG(m_frequency <= 30.0e9,
622  "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
623 
624  // check if hBs and hUt are within the validity range
625  if (hUt < 1.0 || hUt > 10.0)
626  {
627  NS_ABORT_MSG_IF(m_enforceRanges, "Rma UT height out of range");
628  NS_LOG_WARN(
629  "The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
630  }
631 
632  if (hBs < 10.0 || hBs > 150.0)
633  {
634  NS_ABORT_MSG_IF(m_enforceRanges, "Rma BS height out of range");
635  NS_LOG_WARN(
636  "The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
637  }
638 
639  // NOTE The model is intended to be used for BS-UT links, however we may need to
640  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
641  // interference. In order to apply the model, we need to retrieve the values of
642  // hBS and hUT, but in these cases one of the two falls outside the validity
643  // range and the warning message is printed (hBS for the UT-UT case and hUT
644  // for the BS-BS case).
645 
646  // check if the distance is outside the validity range
647  if (distance2D < 10.0 || distance2D > 5.0e3)
648  {
649  NS_ABORT_MSG_IF(m_enforceRanges, "distance2D out of range");
650  NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
651  "accurate");
652  }
653 
654  // compute the pathloss
655  double plNlos = 161.04 - 7.1 * log10(m_w) + 7.5 * log10(m_h) -
656  (24.37 - 3.7 * pow((m_h / hBs), 2)) * log10(hBs) +
657  (43.42 - 3.1 * log10(hBs)) * (log10(distance3D) - 3.0) +
658  20.0 * log10(m_frequency / 1e9) - (3.2 * pow(log10(11.75 * hUt), 2) - 4.97);
659 
660  double loss = std::max(GetLossLos(distance2D, distance3D, hUt, hBs), plNlos);
661 
662  NS_LOG_DEBUG("Loss " << loss);
663 
664  return loss;
665 }
666 
667 double
671 {
672  NS_LOG_FUNCTION(this);
673  double shadowingStd;
674 
675  if (cond == ChannelCondition::LosConditionValue::LOS)
676  {
677  // compute the 2D distance between the two nodes
678  double distance2d = Calculate2dDistance(a->GetPosition(), b->GetPosition());
679 
680  // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 5)
681  double distanceBp = GetBpDistance(m_frequency, a->GetPosition().z, b->GetPosition().z);
682 
683  if (distance2d <= distanceBp)
684  {
685  shadowingStd = 4.0;
686  }
687  else
688  {
689  shadowingStd = 6.0;
690  }
691  }
692  else if (cond == ChannelCondition::LosConditionValue::NLOS)
693  {
694  shadowingStd = 8.0;
695  }
696  else
697  {
698  NS_FATAL_ERROR("Unknown channel condition");
699  }
700 
701  return shadowingStd;
702 }
703 
704 double
707 {
708  NS_LOG_FUNCTION(this);
709  double correlationDistance;
710 
711  // See 3GPP TR 38.901, Table 7.5-6
712  if (cond == ChannelCondition::LosConditionValue::LOS)
713  {
714  correlationDistance = 37;
715  }
716  else if (cond == ChannelCondition::LosConditionValue::NLOS)
717  {
718  correlationDistance = 120;
719  }
720  else
721  {
722  NS_FATAL_ERROR("Unknown channel condition");
723  }
724 
725  return correlationDistance;
726 }
727 
728 double
729 ThreeGppRmaPropagationLossModel::Pl1(double frequency, double distance3D, double h, double /* w */)
730 {
731  double loss = 20.0 * log10(40.0 * M_PI * distance3D * frequency / 1e9 / 3.0) +
732  std::min(0.03 * pow(h, 1.72), 10.0) * log10(distance3D) -
733  std::min(0.044 * pow(h, 1.72), 14.77) + 0.002 * log10(h) * distance3D;
734  return loss;
735 }
736 
737 double
738 ThreeGppRmaPropagationLossModel::GetBpDistance(double frequency, double hA, double hB)
739 {
740  double distanceBp = 2.0 * M_PI * hA * hB * frequency / M_C;
741  return distanceBp;
742 }
743 
744 // ------------------------------------------------------------------------- //
745 
747 
748 TypeId
750 {
751  static TypeId tid = TypeId("ns3::ThreeGppUmaPropagationLossModel")
753  .SetGroupName("Propagation")
754  .AddConstructor<ThreeGppUmaPropagationLossModel>();
755  return tid;
756 }
757 
760 {
761  NS_LOG_FUNCTION(this);
762  m_uniformVar = CreateObject<UniformRandomVariable>();
763  // set a default channel condition model
764  m_channelConditionModel = CreateObject<ThreeGppUmaChannelConditionModel>();
765 }
766 
768 {
769  NS_LOG_FUNCTION(this);
770 }
771 
772 double
773 ThreeGppUmaPropagationLossModel::GetBpDistance(double hUt, double hBs, double distance2D) const
774 {
775  NS_LOG_FUNCTION(this);
776 
777  // compute g (d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
778  double g = 0.0;
779  if (distance2D > 18.0)
780  {
781  g = 5.0 / 4.0 * pow(distance2D / 100.0, 3) * exp(-distance2D / 150.0);
782  }
783 
784  // compute C (hUt, d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
785  double c = 0.0;
786  if (hUt >= 13.0)
787  {
788  c = pow((hUt - 13.0) / 10.0, 1.5) * g;
789  }
790 
791  // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
792  double prob = 1.0 / (1.0 + c);
793  double hE = 0.0;
794  if (m_uniformVar->GetValue() < prob)
795  {
796  hE = 1.0;
797  }
798  else
799  {
800  int random = m_uniformVar->GetInteger(12, std::max(12, (int)(hUt - 1.5)));
801  hE = (double)floor(random / 3.0) * 3.0;
802  }
803 
804  // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
805  double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
806 
807  return distanceBp;
808 }
809 
810 double
812  double distance3D,
813  double hUt,
814  double hBs) const
815 {
816  NS_LOG_FUNCTION(this);
817 
818  // check if hBS and hUT are within the validity range
819  if (hUt < 1.5 || hUt > 22.5)
820  {
821  NS_ABORT_MSG_IF(m_enforceRanges, "Uma UT height out of range");
822  NS_LOG_WARN(
823  "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
824  }
825 
826  if (hBs != 25.0)
827  {
828  NS_ABORT_MSG_IF(m_enforceRanges, "Uma BS height out of range");
829  NS_LOG_WARN("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
830  }
831 
832  // NOTE The model is intended to be used for BS-UT links, however we may need to
833  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
834  // interference. In order to apply the model, we need to retrieve the values of
835  // hBS and hUT, but in these cases one of the two falls outside the validity
836  // range and the warning message is printed (hBS for the UT-UT case and hUT
837  // for the BS-BS case).
838 
839  // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
840  double distanceBp = GetBpDistance(hUt, hBs, distance2D);
841  NS_LOG_DEBUG("breakpoint distance " << distanceBp);
842 
843  // check if the distance is outside the validity range
844  if (distance2D < 10.0 || distance2D > 5.0e3)
845  {
846  NS_ABORT_MSG_IF(m_enforceRanges, "Uma 2D distance out of range");
847  NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
848  "accurate");
849  }
850 
851  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
852  double loss = 0;
853  if (distance2D <= distanceBp)
854  {
855  // use PL1
856  loss = 28.0 + 22.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
857  }
858  else
859  {
860  // use PL2
861  loss = 28.0 + 40.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) -
862  9.0 * log10(pow(distanceBp, 2) + pow(hBs - hUt, 2));
863  }
864 
865  NS_LOG_DEBUG("Loss " << loss);
866 
867  return loss;
868 }
869 
870 double
872 {
873  // distance2dIn is minimum of two independently generated uniformly distributed variables
874  // between 0 and 25 m for UMa and UMi-Street Canyon. 2D−in d shall be UT-specifically generated.
875  return std::min(m_randomO2iVar1->GetValue(0, 25), m_randomO2iVar2->GetValue(0, 25));
876 }
877 
878 double
880  double distance3D,
881  double hUt,
882  double hBs) const
883 {
884  NS_LOG_FUNCTION(this);
885 
886  // check if hBS and hUT are within the vaalidity range
887  if (hUt < 1.5 || hUt > 22.5)
888  {
889  NS_ABORT_MSG_IF(m_enforceRanges, "Uma UT height out of range");
890  NS_LOG_WARN(
891  "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
892  }
893 
894  if (hBs != 25.0)
895  {
896  NS_ABORT_MSG_IF(m_enforceRanges, "Uma BS height out of range");
897  NS_LOG_WARN("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
898  }
899 
900  // NOTE The model is intended to be used for BS-UT links, however we may need to
901  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
902  // interference. In order to apply the model, we need to retrieve the values of
903  // hBS and hUT, but in these cases one of the two falls outside the validity
904  // range and the warning message is printed (hBS for the UT-UT case and hUT
905  // for the BS-BS case).
906 
907  // check if the distance is outside the validity range
908  if (distance2D < 10.0 || distance2D > 5.0e3)
909  {
910  NS_ABORT_MSG_IF(m_enforceRanges, "Uma 2D distance out of range");
911  NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
912  "accurate");
913  }
914 
915  // compute the pathloss
916  double plNlos =
917  13.54 + 39.08 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) - 0.6 * (hUt - 1.5);
918  double loss = std::max(GetLossLos(distance2D, distance3D, hUt, hBs), plNlos);
919  NS_LOG_DEBUG("Loss " << loss);
920 
921  return loss;
922 }
923 
924 double
926  Ptr<MobilityModel> /* b */,
928 {
929  NS_LOG_FUNCTION(this);
930  double shadowingStd;
931 
932  if (cond == ChannelCondition::LosConditionValue::LOS)
933  {
934  shadowingStd = 4.0;
935  }
936  else if (cond == ChannelCondition::LosConditionValue::NLOS)
937  {
938  shadowingStd = 6.0;
939  }
940  else
941  {
942  NS_FATAL_ERROR("Unknown channel condition");
943  }
944 
945  return shadowingStd;
946 }
947 
948 double
951 {
952  NS_LOG_FUNCTION(this);
953  double correlationDistance;
954 
955  // See 3GPP TR 38.901, Table 7.5-6
956  if (cond == ChannelCondition::LosConditionValue::LOS)
957  {
958  correlationDistance = 37;
959  }
960  else if (cond == ChannelCondition::LosConditionValue::NLOS)
961  {
962  correlationDistance = 50;
963  }
964  else
965  {
966  NS_FATAL_ERROR("Unknown channel condition");
967  }
968 
969  return correlationDistance;
970 }
971 
972 int64_t
974 {
975  NS_LOG_FUNCTION(this);
976 
977  m_normRandomVariable->SetStream(stream);
978  m_uniformVar->SetStream(stream + 1);
979  return 2;
980 }
981 
982 // ------------------------------------------------------------------------- //
983 
985 
986 TypeId
988 {
989  static TypeId tid = TypeId("ns3::ThreeGppUmiStreetCanyonPropagationLossModel")
991  .SetGroupName("Propagation")
993  return tid;
994 }
995 
998 {
999  NS_LOG_FUNCTION(this);
1000 
1001  // set a default channel condition model
1002  m_channelConditionModel = CreateObject<ThreeGppUmiStreetCanyonChannelConditionModel>();
1003 }
1004 
1006 {
1007  NS_LOG_FUNCTION(this);
1008 }
1009 
1010 double
1012  double hBs,
1013  double /* distance2D */) const
1014 {
1015  NS_LOG_FUNCTION(this);
1016 
1017  // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1018  double hE = 1.0;
1019 
1020  // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1021  double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
1022 
1023  return distanceBp;
1024 }
1025 
1026 double
1028 {
1029  // distance2dIn is minimum of two independently generated uniformly distributed variables
1030  // between 0 and 25 m for UMa and UMi-Street Canyon. 2D−in d shall be UT-specifically generated.
1031  return std::min(m_randomO2iVar1->GetValue(0, 25), m_randomO2iVar2->GetValue(0, 25));
1032 }
1033 
1034 double
1036  double distance3D,
1037  double hUt,
1038  double hBs) const
1039 {
1040  NS_LOG_FUNCTION(this);
1041 
1042  // check if hBS and hUT are within the validity range
1043  if (hUt < 1.5 || hUt >= 10.0)
1044  {
1045  NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon UT height out of range");
1046  NS_LOG_WARN(
1047  "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). "
1048  "We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
1049  }
1050 
1051  if (hBs != 10.0)
1052  {
1053  NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon BS height out of range");
1054  NS_LOG_WARN("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
1055  }
1056 
1057  // NOTE The model is intended to be used for BS-UT links, however we may need to
1058  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1059  // interference. In order to apply the model, we need to retrieve the values of
1060  // hBS and hUT, but in these cases one of the two falls outside the validity
1061  // range and the warning message is printed (hBS for the UT-UT case and hUT
1062  // for the BS-BS case).
1063 
1064  // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
1065  double distanceBp = GetBpDistance(hUt, hBs, distance2D);
1066  NS_LOG_DEBUG("breakpoint distance " << distanceBp);
1067 
1068  // check if the distance is outside the validity range
1069  if (distance2D < 10.0 || distance2D > 5.0e3)
1070  {
1071  NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon 2D distance out of range");
1072  NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1073  "accurate");
1074  }
1075 
1076  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1077  double loss = 0;
1078  if (distance2D <= distanceBp)
1079  {
1080  // use PL1
1081  loss = 32.4 + 21.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1082  }
1083  else
1084  {
1085  // use PL2
1086  loss = 32.4 + 40.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) -
1087  9.5 * log10(pow(distanceBp, 2) + pow(hBs - hUt, 2));
1088  }
1089 
1090  NS_LOG_DEBUG("Loss " << loss);
1091 
1092  return loss;
1093 }
1094 
1095 double
1097  double distance3D,
1098  double hUt,
1099  double hBs) const
1100 {
1101  NS_LOG_FUNCTION(this);
1102 
1103  // check if hBS and hUT are within the validity range
1104  if (hUt < 1.5 || hUt >= 10.0)
1105  {
1106  NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon UT height out of range");
1107  NS_LOG_WARN(
1108  "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). "
1109  "We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
1110  }
1111 
1112  if (hBs != 10.0)
1113  {
1114  NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon BS height out of range");
1115  NS_LOG_WARN("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
1116  }
1117 
1118  // NOTE The model is intended to be used for BS-UT links, however we may need to
1119  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1120  // interference. In order to apply the model, we need to retrieve the values of
1121  // hBS and hUT, but in these cases one of the two falls outside the validity
1122  // range and the warning message is printed (hBS for the UT-UT case and hUT
1123  // for the BS-BS case).
1124 
1125  // check if the distance is outside the validity range
1126  if (distance2D < 10.0 || distance2D > 5.0e3)
1127  {
1128  NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon 2D distance out of range");
1129  NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1130  "accurate");
1131  }
1132 
1133  // compute the pathloss
1134  double plNlos =
1135  22.4 + 35.3 * log10(distance3D) + 21.3 * log10(m_frequency / 1e9) - 0.3 * (hUt - 1.5);
1136  double loss = std::max(GetLossLos(distance2D, distance3D, hUt, hBs), plNlos);
1137  NS_LOG_DEBUG("Loss " << loss);
1138 
1139  return loss;
1140 }
1141 
1142 std::pair<double, double>
1144 {
1145  NS_LOG_FUNCTION(this);
1146  // TR 38.901 specifies hBS = 10 m and 1.5 <= hUT <= 22.5
1147  double hBs;
1148  double hUt;
1149  if (za == 10.0)
1150  {
1151  // node A is the BS and node B is the UT
1152  hBs = za;
1153  hUt = zb;
1154  }
1155  else if (zb == 10.0)
1156  {
1157  // node B is the BS and node A is the UT
1158  hBs = zb;
1159  hUt = za;
1160  }
1161  else
1162  {
1163  // We cannot know who is the BS and who is the UT, we assume that the
1164  // tallest node is the BS and the smallest is the UT
1165  hBs = std::max(za, zb);
1166  hUt = std::min(za, za);
1167  }
1168 
1169  return std::pair<double, double>(hUt, hBs);
1170 }
1171 
1172 double
1174  Ptr<MobilityModel> /* a */,
1175  Ptr<MobilityModel> /* b */,
1177 {
1178  NS_LOG_FUNCTION(this);
1179  double shadowingStd;
1180 
1181  if (cond == ChannelCondition::LosConditionValue::LOS)
1182  {
1183  shadowingStd = 4.0;
1184  }
1185  else if (cond == ChannelCondition::LosConditionValue::NLOS)
1186  {
1187  shadowingStd = 7.82;
1188  }
1189  else
1190  {
1191  NS_FATAL_ERROR("Unknown channel condition");
1192  }
1193 
1194  return shadowingStd;
1195 }
1196 
1197 double
1200 {
1201  NS_LOG_FUNCTION(this);
1202  double correlationDistance;
1203 
1204  // See 3GPP TR 38.901, Table 7.5-6
1205  if (cond == ChannelCondition::LosConditionValue::LOS)
1206  {
1207  correlationDistance = 10;
1208  }
1209  else if (cond == ChannelCondition::LosConditionValue::NLOS)
1210  {
1211  correlationDistance = 13;
1212  }
1213  else
1214  {
1215  NS_FATAL_ERROR("Unknown channel condition");
1216  }
1217 
1218  return correlationDistance;
1219 }
1220 
1221 // ------------------------------------------------------------------------- //
1222 
1224 
1225 TypeId
1227 {
1228  static TypeId tid = TypeId("ns3::ThreeGppIndoorOfficePropagationLossModel")
1230  .SetGroupName("Propagation")
1231  .AddConstructor<ThreeGppIndoorOfficePropagationLossModel>();
1232  return tid;
1233 }
1234 
1237 {
1238  NS_LOG_FUNCTION(this);
1239 
1240  // set a default channel condition model
1241  m_channelConditionModel = CreateObject<ThreeGppIndoorOpenOfficeChannelConditionModel>();
1242 }
1243 
1245 {
1246  NS_LOG_FUNCTION(this);
1247 }
1248 
1249 double
1251 {
1252  return 0;
1253 }
1254 
1255 double
1257  double distance3D,
1258  double /* hUt */,
1259  double /* hBs */) const
1260 {
1261  NS_LOG_FUNCTION(this);
1262 
1263  // check if the distance is outside the validity range
1264  if (distance3D < 1.0 || distance3D > 150.0)
1265  {
1266  NS_ABORT_MSG_IF(m_enforceRanges, "IndoorOffice 3D distance out of range");
1267  NS_LOG_WARN("The 3D distance is outside the validity range, the pathloss value may not be "
1268  "accurate");
1269  }
1270 
1271  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1272  double loss = 32.4 + 17.3 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1273 
1274  NS_LOG_DEBUG("Loss " << loss);
1275 
1276  return loss;
1277 }
1278 
1279 double
1281  double distance3D,
1282  double hUt,
1283  double hBs) const
1284 {
1285  NS_LOG_FUNCTION(this);
1286 
1287  // check if the distance is outside the validity range
1288  if (distance3D < 1.0 || distance3D > 150.0)
1289  {
1290  NS_ABORT_MSG_IF(m_enforceRanges, "IndoorOffice 3D distance out of range");
1291  NS_LOG_WARN("The 3D distance is outside the validity range, the pathloss value may not be "
1292  "accurate");
1293  }
1294 
1295  // compute the pathloss
1296  double plNlos = 17.3 + 38.3 * log10(distance3D) + 24.9 * log10(m_frequency / 1e9);
1297  double loss = std::max(GetLossLos(distance2D, distance3D, hUt, hBs), plNlos);
1298 
1299  NS_LOG_DEBUG("Loss " << loss);
1300 
1301  return loss;
1302 }
1303 
1304 double
1306  Ptr<MobilityModel> /* a */,
1307  Ptr<MobilityModel> /* b */,
1309 {
1310  NS_LOG_FUNCTION(this);
1311  double shadowingStd;
1312 
1313  if (cond == ChannelCondition::LosConditionValue::LOS)
1314  {
1315  shadowingStd = 3.0;
1316  }
1317  else if (cond == ChannelCondition::LosConditionValue::NLOS)
1318  {
1319  shadowingStd = 8.03;
1320  }
1321  else
1322  {
1323  NS_FATAL_ERROR("Unknown channel condition");
1324  }
1325 
1326  return shadowingStd;
1327 }
1328 
1329 double
1332 {
1333  NS_LOG_FUNCTION(this);
1334 
1335  // See 3GPP TR 38.901, Table 7.5-6
1336  double correlationDistance;
1337 
1338  if (cond == ChannelCondition::LosConditionValue::LOS)
1339  {
1340  correlationDistance = 10;
1341  }
1342  else if (cond == ChannelCondition::LosConditionValue::NLOS)
1343  {
1344  correlationDistance = 6;
1345  }
1346  else
1347  {
1348  NS_FATAL_ERROR("Unknown channel condition");
1349  }
1350 
1351  return correlationDistance;
1352 }
1353 
1354 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
double f(double x, void *params)
Definition: 80211b.c:71
#define max(a, b)
Definition: 80211b.c:43
AttributeValue implementation for Boolean.
Definition: boolean.h:37
LosConditionValue
Possible values for Line-of-Sight condition.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Vector GetPosition() const
A network Node.
Definition: node.h:56
uint32_t GetId() const
Definition: node.cc:117
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Models the propagation loss through a transmission medium.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
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(double distance2D, double distance3D, double hUt, double hBs) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
double GetLossLos(double distance2D, double distance3D, double hUt, double hBs) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
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.
double GetLoss(Ptr< ChannelCondition > cond, double distance2D, double distance3D, double hUt, double hBs) const
Computes the pathloss between a and b.
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.
Ptr< UniformRandomVariable > m_randomO2iVar1
a uniform random variable for the calculation of the indoor loss, see TR38.901 Table 7....
virtual double GetLossNlos(double distance2D, double distance3D, double hUt, double hBs) const =0
Computes the pathloss between a and b considering that the line of sight is obstructed.
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 GetLossLos(double distance2D, double distance3D, double hUt, double hBs) const =0
Computes the pathloss between a and b considering that the line of sight is not obstructed.
int64_t DoAssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
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.
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.
virtual double GetLossNlosv(double distance2D, double distance3D, double hUt, double hBs) const
Computes the pathloss between a and b considering that the line of sight is obstructed by a vehicle.
Ptr< NormalRandomVariable > m_normalO2iHighLossVar
a normal random variable for the calculation of 02i high loss, see TR38.901 Table 7....
virtual std::pair< double, double > GetUtAndBsHeights(double za, double zb) const
Determines hUT and hBS.
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
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the RMa scenario.
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 GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetLossLos(double distance2D, double distance3D, double hUt, double hBs) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetLossNlos(double distance2D, double distance3D, double hUt, double hBs) 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 m_h
average building height in meters
static double GetBpDistance(double frequency, double hA, double hB)
Computes the breakpoint distance for the RMa scenario.
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the UMa scenario.
double GetLossLos(double distance2D, double distance3D, double hUt, double hBs) const override
Computes the pathloss between a and b considering that the line of sight is not 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 GetLossNlos(double distance2D, double distance3D, double hUt, double hBs) const override
Computes the pathloss between a and b considering that the line of sight is 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...
std::pair< double, double > GetUtAndBsHeights(double za, double zb) const override
Determines hUT and hBS.
double GetLossNlos(double distance2D, double distance3D, double hUt, double hBs) 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(double distance2D, double distance3D, double hUt, double hBs) 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:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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:183
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 > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
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:43
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:231
#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
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static const double M_C
propagation velocity in free space
double CalculateDistance(const Vector3D &a, const Vector3D &b)
Definition: vector.cc:109