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