A Discrete-Event Network Simulator
API
three-gpp-propagation-loss-model.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2019 SIGNET Lab, Department of Information Engineering,
4  * University of Padova
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */
19 
21 #include "ns3/log.h"
22 #include "ns3/mobility-model.h"
23 #include "ns3/channel-condition-model.h"
24 #include "ns3/double.h"
25 #include "ns3/boolean.h"
26 #include "ns3/pointer.h"
27 #include <cmath>
28 #include "ns3/node.h"
29 #include "ns3/simulator.h"
30 
31 namespace ns3 {
32 
33 NS_LOG_COMPONENT_DEFINE ("ThreeGppPropagationLossModel");
34 
35 static const double M_C = 3.0e8; // propagation velocity in free space
36 
37 // ------------------------------------------------------------------------- //
38 
40 
41 TypeId
43 {
44  static TypeId tid = TypeId ("ns3::ThreeGppPropagationLossModel")
46  .SetGroupName ("Propagation")
47  .AddAttribute ("Frequency", "The centre frequency in Hz.",
48  DoubleValue (500.0e6),
51  MakeDoubleChecker<double> ())
52  .AddAttribute ("ShadowingEnabled", "Enable/disable shadowing.",
53  BooleanValue (true),
56  .AddAttribute ("ChannelConditionModel", "Pointer to the channel condition model.",
57  PointerValue (),
60  MakePointerChecker<ChannelConditionModel> ())
61  ;
62  return tid;
63 }
64 
67 {
68  NS_LOG_FUNCTION (this);
69 
70  // initialize the normal random variable
71  m_normRandomVariable = CreateObject<NormalRandomVariable> ();
72  m_normRandomVariable->SetAttribute ("Mean", DoubleValue (0));
73  m_normRandomVariable->SetAttribute ("Variance", DoubleValue (1));
74 }
75 
77 {
78  NS_LOG_FUNCTION (this);
79 }
80 
81 void
83 {
84  m_channelConditionModel->Dispose ();
85  m_channelConditionModel = nullptr;
86  m_shadowingMap.clear ();
87 }
88 
89 void
91 {
92  NS_LOG_FUNCTION (this);
94 }
95 
98 {
99  NS_LOG_FUNCTION (this);
101 }
102 
103 void
105 {
106  NS_LOG_FUNCTION (this);
107  NS_ASSERT_MSG (f >= 500.0e6 && f <= 100.0e9, "Frequency should be between 0.5 and 100 GHz but is " << f);
108  m_frequency = f;
109 }
110 
111 double
113 {
114  NS_LOG_FUNCTION (this);
115  return m_frequency;
116 }
117 
118 double
121  Ptr<MobilityModel> b) const
122 {
123  NS_LOG_FUNCTION (this);
124 
125  // check if the model is initialized
126  NS_ASSERT_MSG (m_frequency != 0.0, "First set the centre frequency");
127 
128  // retrieve the channel condition
129  NS_ASSERT_MSG (m_channelConditionModel, "First set the channel condition model");
130  Ptr<ChannelCondition> cond = m_channelConditionModel->GetChannelCondition (a, b);
131 
132  // compute the 2D distance between a and b
133  double distance2d = Calculate2dDistance (a->GetPosition (), b->GetPosition ());
134 
135  // compute the 3D distance between a and b
136  double distance3d = CalculateDistance (a->GetPosition (), b->GetPosition ());
137 
138  // compute hUT and hBS
139  std::pair<double, double> heights = GetUtAndBsHeights (a->GetPosition ().z, b->GetPosition ().z);
140 
141  double rxPow = txPowerDbm;
142  if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::LOS)
143  {
144  rxPow -= GetLossLos (distance2d, distance3d, heights.first, heights.second);
145  NS_LOG_DEBUG ("Channel codition is LOS, rxPower = " << rxPow);
146  }
147  else if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::NLOS)
148  {
149  rxPow -= GetLossNlos (distance2d, distance3d, heights.first, heights.second);
150  NS_LOG_DEBUG ("Channel codition is NLOS, rxPower = " << rxPow);
151  }
152  else
153  {
154  NS_FATAL_ERROR ("Unknown channel condition");
155  }
156 
157  if (m_shadowingEnabled)
158  {
159  rxPow -= GetShadowing (a, b, cond->GetLosCondition ());
160  }
161 
162  return rxPow;
163 }
164 
165 double
167 {
168  NS_LOG_FUNCTION (this);
169 
170  double shadowingValue;
171 
172  // compute the channel key
173  uint32_t key = GetKey (a, b);
174 
175  bool notFound = false; // indicates if the shadowing value has not been computed yet
176  bool newCondition = false; // indicates if the channel condition has changed
177  Vector newDistance; // the distance vector, that is not a distance but a difference
178  auto it = m_shadowingMap.end (); // the shadowing map iterator
179  if (m_shadowingMap.find (key) != m_shadowingMap.end ())
180  {
181  // found the shadowing value in the map
182  it = m_shadowingMap.find (key);
183  newDistance = GetVectorDifference (a, b);
184  newCondition = (it->second.m_condition != cond); // true if the condition changed
185  }
186  else
187  {
188  notFound = true;
189 
190  // add a new entry in the map and update the iterator
191  ShadowingMapItem newItem;
192  it = m_shadowingMap.insert (it, std::make_pair (key, newItem));
193  }
194 
195  if (notFound || newCondition)
196  {
197  // generate a new independent realization
198  shadowingValue = m_normRandomVariable->GetValue () * GetShadowingStd (a, b, cond);
199  }
200  else
201  {
202  // compute a new correlated shadowing loss
203  Vector2D displacement (newDistance.x - it->second.m_distance.x, newDistance.y - it->second.m_distance.y);
204  double R = exp (-1 * displacement.GetLength () / GetShadowingCorrelationDistance (cond));
205  shadowingValue = R * it->second.m_shadowing + sqrt (1 - R * R) * m_normRandomVariable->GetValue () * GetShadowingStd (a, b, cond);
206  }
207 
208  // update the entry in the map
209  it->second.m_shadowing = shadowingValue;
210  it->second.m_distance = newDistance; // Save the (0,0,0) vector in case it's the first time we are calculating this value
211  it->second.m_condition = cond;
212 
213  return shadowingValue;
214 }
215 
216 std::pair<double, double>
218 {
219  // The default implementation assumes that the tallest node is the BS and the
220  // smallest is the UT.
221  double hUt = std::min (za, zb);
222  double hBs = std::max (za, zb);
223 
224  return std::pair<double, double> (hUt, hBs);
225 }
226 
227 int64_t
229 {
230  NS_LOG_FUNCTION (this);
231 
232  m_normRandomVariable->SetStream (stream);
233  return 1;
234 }
235 
236 double
238 {
239  double x = a.x - b.x;
240  double y = a.y - b.y;
241  double distance2D = sqrt (x * x + y * y);
242 
243  return distance2D;
244 }
245 
246 uint32_t
248 {
249  // use the nodes ids to obtain an unique key for the channel between a and b
250  // sort the nodes ids so that the key is reciprocal
251  uint32_t x1 = std::min (a->GetObject<Node> ()->GetId (), b->GetObject<Node> ()->GetId ());
252  uint32_t x2 = std::max (a->GetObject<Node> ()->GetId (), b->GetObject<Node> ()->GetId ());
253 
254  // use the cantor function to obtain the key
255  uint32_t key = (((x1 + x2) * (x1 + x2 + 1)) / 2) + x2;
256 
257  return key;
258 }
259 
260 Vector
262 {
263  uint32_t x1 = a->GetObject<Node> ()->GetId ();
264  uint32_t x2 = b->GetObject<Node> ()->GetId ();
265 
266  if (x1 < x2)
267  {
268  return b->GetPosition () - a->GetPosition ();
269  }
270  else
271  {
272  return a->GetPosition () - b->GetPosition ();
273  }
274 }
275 
276 // ------------------------------------------------------------------------- //
277 
279 
280 TypeId
282 {
283  static TypeId tid = TypeId ("ns3::ThreeGppRmaPropagationLossModel")
285  .SetGroupName ("Propagation")
286  .AddConstructor<ThreeGppRmaPropagationLossModel> ()
287  .AddAttribute ("AvgBuildingHeight", "The average building height in meters.",
288  DoubleValue (5.0),
290  MakeDoubleChecker<double> (5.0, 50.0))
291  .AddAttribute ("AvgStreetWidth", "The average street width in meters.",
292  DoubleValue (20.0),
294  MakeDoubleChecker<double> (5.0, 50.0))
295  ;
296  return tid;
297 }
298 
301 {
302  NS_LOG_FUNCTION (this);
303 
304  // set a default channel condition model
305  m_channelConditionModel = CreateObject<ThreeGppRmaChannelConditionModel> ();
306 }
307 
309 {
310  NS_LOG_FUNCTION (this);
311 }
312 
313 double
314 ThreeGppRmaPropagationLossModel::GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const
315 {
316  NS_LOG_FUNCTION (this);
317  NS_ASSERT_MSG (m_frequency <= 30.0e9, "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
318 
319  // check if hBS and hUT are within the specified validity range
320  if (hUt < 1.0 || hUt > 10.0)
321  {
322  NS_LOG_WARN ("The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
323  }
324 
325  if (hBs < 10.0 || hBs > 150.0)
326  {
327  NS_LOG_WARN ("The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
328  }
329 
330  // NOTE The model is intended to be used for BS-UT links, however we may need to
331  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
332  // interference. In order to apply the model, we need to retrieve the values of
333  // hBS and hUT, but in these cases one of the two falls outside the validity
334  // range and the warning message is printed (hBS for the UT-UT case and hUT
335  // for the BS-BS case).
336 
337  double distanceBp = GetBpDistance (m_frequency, hBs, hUt);
338  NS_LOG_DEBUG ("breakpoint distance " << distanceBp);
339 
340  // check if the distace is outside the validity range
341  if (distance2D < 10.0 || distance2D > 10.0e3)
342  {
343  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
344  }
345 
346  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
347  double loss = 0;
348  if (distance2D <= distanceBp)
349  {
350  // use PL1
351  loss = Pl1 (m_frequency, distance3D, m_h, m_w);
352  }
353  else
354  {
355  // use PL2
356  loss = Pl1 (m_frequency, distanceBp, m_h, m_w) + 40 * log10 (distance3D / distanceBp);
357  }
358 
359  NS_LOG_DEBUG ("Loss " << loss);
360 
361  return loss;
362 }
363 
364 double
365 ThreeGppRmaPropagationLossModel::GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const
366 {
367  NS_LOG_FUNCTION (this);
368  NS_ASSERT_MSG (m_frequency <= 30.0e9, "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
369 
370  // check if hBs and hUt are within the validity range
371  if (hUt < 1.0 || hUt > 10.0)
372  {
373  NS_LOG_WARN ("The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
374  }
375 
376  if (hBs < 10.0 || hBs > 150.0)
377  {
378  NS_LOG_WARN ("The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
379  }
380 
381  // NOTE The model is intended to be used for BS-UT links, however we may need to
382  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
383  // interference. In order to apply the model, we need to retrieve the values of
384  // hBS and hUT, but in these cases one of the two falls outside the validity
385  // range and the warning message is printed (hBS for the UT-UT case and hUT
386  // for the BS-BS case).
387 
388  // check if the distace is outside the validity range
389  if (distance2D < 10.0 || distance2D > 5.0e3)
390  {
391  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
392  }
393 
394  // compute the pathloss
395  double plNlos = 161.04 - 7.1 * log10 (m_w) + 7.5 * log10 (m_h) - (24.37 - 3.7 * pow ((m_h / hBs), 2)) * log10 (hBs) + (43.42 - 3.1 * log10 (hBs)) * (log10 (distance3D) - 3.0) + 20.0 * log10 (m_frequency / 1e9) - (3.2 * pow (log10 (11.75 * hUt), 2) - 4.97);
396 
397  double loss = std::max (GetLossLos (distance2D, distance3D, hUt, hBs), plNlos);
398 
399  NS_LOG_DEBUG ("Loss " << loss);
400 
401  return loss;
402 }
403 
404 double
406 {
407  NS_LOG_FUNCTION (this);
408  double shadowingStd;
409 
410  if (cond == ChannelCondition::LosConditionValue::LOS)
411  {
412  // compute the 2D distance between the two nodes
413  double distance2d = Calculate2dDistance (a->GetPosition (), b->GetPosition ());
414 
415  // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 5)
416  double distanceBp = GetBpDistance (m_frequency, a->GetPosition ().z, b->GetPosition ().z);
417 
418  if (distance2d <= distanceBp)
419  {
420  shadowingStd = 4.0;
421  }
422  else
423  {
424  shadowingStd = 6.0;
425  }
426  }
427  else if (cond == ChannelCondition::LosConditionValue::NLOS)
428  {
429  shadowingStd = 8.0;
430  }
431  else
432  {
433  NS_FATAL_ERROR ("Unknown channel condition");
434  }
435 
436  return shadowingStd;
437 }
438 
439 double
441 {
442  NS_LOG_FUNCTION (this);
443  double correlationDistance;
444 
445  // See 3GPP TR 38.901, Table 7.5-6
446  if (cond == ChannelCondition::LosConditionValue::LOS)
447  {
448  correlationDistance = 37;
449  }
450  else if (cond == ChannelCondition::LosConditionValue::NLOS)
451  {
452  correlationDistance = 120;
453  }
454  else
455  {
456  NS_FATAL_ERROR ("Unknown channel condition");
457  }
458 
459  return correlationDistance;
460 }
461 
462 double
463 ThreeGppRmaPropagationLossModel::Pl1 (double frequency, double distance3D, double h, double w)
464 {
465  NS_UNUSED (w);
466  double loss = 20.0 * log10 (40.0 * M_PI * distance3D * frequency / 1e9 / 3.0) + std::min (0.03 * pow (h, 1.72), 10.0) * log10 (distance3D) - std::min (0.044 * pow (h, 1.72), 14.77) + 0.002 * log10 (h) * distance3D;
467  return loss;
468 }
469 
470 double
471 ThreeGppRmaPropagationLossModel::GetBpDistance (double frequency, double hA, double hB)
472 {
473  double distanceBp = 2.0 * M_PI * hA * hB * frequency / M_C;
474  return distanceBp;
475 }
476 
477 // ------------------------------------------------------------------------- //
478 
480 
481 TypeId
483 {
484  static TypeId tid = TypeId ("ns3::ThreeGppUmaPropagationLossModel")
486  .SetGroupName ("Propagation")
487  .AddConstructor<ThreeGppUmaPropagationLossModel> ()
488  ;
489  return tid;
490 }
491 
494 {
495  NS_LOG_FUNCTION (this);
496  m_uniformVar = CreateObject<UniformRandomVariable> ();
497 
498  // set a default channel condition model
499  m_channelConditionModel = CreateObject<ThreeGppUmaChannelConditionModel> ();
500 }
501 
503 {
504  NS_LOG_FUNCTION (this);
505 }
506 
507 double
508 ThreeGppUmaPropagationLossModel::GetBpDistance (double hUt, double hBs, double distance2D) const
509 {
510  NS_LOG_FUNCTION (this);
511 
512  // compute g (d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
513  double g = 0.0;
514  if (distance2D > 18.0)
515  {
516  g = 5.0 / 4.0 * pow (distance2D / 100.0, 3) * exp (-distance2D / 150.0);
517  }
518 
519  // compute C (hUt, d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
520  double c = 0.0;
521  if (hUt >= 13.0)
522  {
523  c = pow ((hUt - 13.0) / 10.0, 1.5) * g;
524  }
525 
526  // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
527  double prob = 1.0 / (1.0 + c);
528  double hE = 0.0;
529  if (m_uniformVar->GetValue () < prob)
530  {
531  hE = 1.0;
532  }
533  else
534  {
535  int random = m_uniformVar->GetInteger (12, (int)(hUt - 1.5));
536  hE = (double)floor (random / 3.0) * 3.0;
537  }
538 
539  // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
540  double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
541 
542  return distanceBp;
543 }
544 
545 double
546 ThreeGppUmaPropagationLossModel::GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const
547 {
548  NS_LOG_FUNCTION (this);
549 
550  // check if hBS and hUT are within the validity range
551  if (hUt < 1.5 || hUt > 22.5)
552  {
553  NS_LOG_WARN ("The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
554  }
555 
556  if (hBs != 25.0)
557  {
558  NS_LOG_WARN ("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
559  }
560 
561  // NOTE The model is intended to be used for BS-UT links, however we may need to
562  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
563  // interference. In order to apply the model, we need to retrieve the values of
564  // hBS and hUT, but in these cases one of the two falls outside the validity
565  // range and the warning message is printed (hBS for the UT-UT case and hUT
566  // for the BS-BS case).
567 
568  // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
569  double distanceBp = GetBpDistance (hUt, hBs, distance2D);
570  NS_LOG_DEBUG ("breakpoint distance " << distanceBp);
571 
572  // check if the distace is outside the validity range
573  if (distance2D < 10.0 || distance2D > 5.0e3)
574  {
575  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
576  }
577 
578  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
579  double loss = 0;
580  if (distance2D <= distanceBp)
581  {
582  // use PL1
583  loss = 28.0 + 22.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9);
584  }
585  else
586  {
587  // use PL2
588  loss = 28.0 + 40.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9) - 9.0 * log10 (pow (distanceBp, 2) + pow (hBs - hUt, 2));
589  }
590 
591  NS_LOG_DEBUG ("Loss " << loss);
592 
593  return loss;
594 }
595 
596 double
597 ThreeGppUmaPropagationLossModel::GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const
598 {
599  NS_LOG_FUNCTION (this);
600 
601  // check if hBS and hUT are within the vaalidity range
602  if (hUt < 1.5 || hUt > 22.5)
603  {
604  NS_LOG_WARN ("The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
605  }
606 
607  if (hBs != 25.0)
608  {
609  NS_LOG_WARN ("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
610  }
611 
612  // NOTE The model is intended to be used for BS-UT links, however we may need to
613  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
614  // interference. In order to apply the model, we need to retrieve the values of
615  // hBS and hUT, but in these cases one of the two falls outside the validity
616  // range and the warning message is printed (hBS for the UT-UT case and hUT
617  // for the BS-BS case).
618 
619  // check if the distace is outside the validity range
620  if (distance2D < 10.0 || distance2D > 5.0e3)
621  {
622  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
623  }
624 
625  // compute the pathloss
626  double plNlos = 13.54 + 39.08 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9) - 0.6 * (hUt - 1.5);
627  double loss = std::max (GetLossLos (distance2D, distance3D, hUt, hBs), plNlos);
628  NS_LOG_DEBUG ("Loss " << loss);
629 
630  return loss;
631 }
632 
633 double
635 {
636  NS_LOG_FUNCTION (this);
637  NS_UNUSED (a);
638  NS_UNUSED (b);
639  double shadowingStd;
640 
641  if (cond == ChannelCondition::LosConditionValue::LOS)
642  {
643  shadowingStd = 4.0;
644  }
645  else if (cond == ChannelCondition::LosConditionValue::NLOS)
646  {
647  shadowingStd = 6.0;
648  }
649  else
650  {
651  NS_FATAL_ERROR ("Unknown channel condition");
652  }
653 
654  return shadowingStd;
655 }
656 
657 double
659 {
660  NS_LOG_FUNCTION (this);
661  double correlationDistance;
662 
663  // See 3GPP TR 38.901, Table 7.5-6
664  if (cond == ChannelCondition::LosConditionValue::LOS)
665  {
666  correlationDistance = 37;
667  }
668  else if (cond == ChannelCondition::LosConditionValue::NLOS)
669  {
670  correlationDistance = 50;
671  }
672  else
673  {
674  NS_FATAL_ERROR ("Unknown channel condition");
675  }
676 
677  return correlationDistance;
678 }
679 
680 int64_t
682 {
683  NS_LOG_FUNCTION (this);
684 
685  m_normRandomVariable->SetStream (stream);
686  m_uniformVar->SetStream (stream);
687  return 2;
688 }
689 
690 // ------------------------------------------------------------------------- //
691 
693 
694 TypeId
696 {
697  static TypeId tid = TypeId ("ns3::ThreeGppUmiStreetCanyonPropagationLossModel")
699  .SetGroupName ("Propagation")
701  ;
702  return tid;
703 }
706 {
707  NS_LOG_FUNCTION (this);
708 
709  // set a default channel condition model
710  m_channelConditionModel = CreateObject<ThreeGppUmiStreetCanyonChannelConditionModel> ();
711 }
712 
714 {
715  NS_LOG_FUNCTION (this);
716 }
717 
718 double
719 ThreeGppUmiStreetCanyonPropagationLossModel::GetBpDistance (double hUt, double hBs, double distance2D) const
720 {
721  NS_LOG_FUNCTION (this);
722  NS_UNUSED (distance2D);
723 
724  // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
725  double hE = 1.0;
726 
727  // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
728  double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
729 
730  return distanceBp;
731 }
732 
733 double
734 ThreeGppUmiStreetCanyonPropagationLossModel::GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const
735 {
736  NS_LOG_FUNCTION (this);
737 
738  // check if hBS and hUT are within the validity range
739  if (hUt < 1.5 || hUt >= 10.0)
740  {
741  NS_LOG_WARN ("The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
742  }
743 
744  if (hBs != 10.0)
745  {
746  NS_LOG_WARN ("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
747  }
748 
749  // NOTE The model is intended to be used for BS-UT links, however we may need to
750  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
751  // interference. In order to apply the model, we need to retrieve the values of
752  // hBS and hUT, but in these cases one of the two falls outside the validity
753  // range and the warning message is printed (hBS for the UT-UT case and hUT
754  // for the BS-BS case).
755 
756  // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
757  double distanceBp = GetBpDistance (hUt, hBs, distance2D);
758  NS_LOG_DEBUG ("breakpoint distance " << distanceBp);
759 
760  // check if the distace is outside the validity range
761  if (distance2D < 10.0 || distance2D > 5.0e3)
762  {
763  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
764  }
765 
766  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
767  double loss = 0;
768  if (distance2D <= distanceBp)
769  {
770  // use PL1
771  loss = 32.4 + 21.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9);
772  }
773  else
774  {
775  // use PL2
776  loss = 32.4 + 40.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9) - 9.5 * log10 (pow (distanceBp, 2) + pow (hBs - hUt, 2));
777  }
778 
779  NS_LOG_DEBUG ("Loss " << loss);
780 
781  return loss;
782 }
783 
784 double
785 ThreeGppUmiStreetCanyonPropagationLossModel::GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const
786 {
787  NS_LOG_FUNCTION (this);
788 
789  // check if hBS and hUT are within the validity range
790  if (hUt < 1.5 || hUt >= 10.0)
791  {
792  NS_LOG_WARN ("The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
793  }
794 
795  if (hBs != 10.0)
796  {
797  NS_LOG_WARN ("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
798  }
799 
800  // NOTE The model is intended to be used for BS-UT links, however we may need to
801  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
802  // interference. In order to apply the model, we need to retrieve the values of
803  // hBS and hUT, but in these cases one of the two falls outside the validity
804  // range and the warning message is printed (hBS for the UT-UT case and hUT
805  // for the BS-BS case).
806 
807  // check if the distace is outside the validity range
808  if (distance2D < 10.0 || distance2D > 5.0e3)
809  {
810  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
811  }
812 
813  // compute the pathloss
814  double plNlos = 22.4 + 35.3 * log10 (distance3D) + 21.3 * log10 (m_frequency / 1e9) - 0.3 * (hUt - 1.5);
815  double loss = std::max (GetLossLos (distance2D, distance3D, hUt, hBs), plNlos);
816  NS_LOG_DEBUG ("Loss " << loss);
817 
818  return loss;
819 }
820 
821 std::pair<double, double>
823 {
824  NS_LOG_FUNCTION (this);
825  // TR 38.901 specifies hBS = 10 m and 1.5 <= hUT <= 22.5
826  double hBs, hUt;
827  if (za == 10.0)
828  {
829  // node A is the BS and node B is the UT
830  hBs = za;
831  hUt = zb;
832  }
833  else if (zb == 10.0)
834  {
835  // node B is the BS and node A is the UT
836  hBs = zb;
837  hUt = za;
838  }
839  else
840  {
841  // We cannot know who is the BS and who is the UT, we assume that the
842  // tallest node is the BS and the smallest is the UT
843  hBs = std::max (za, zb);
844  hUt = std::min (za, za);
845  }
846 
847  return std::pair<double, double> (hUt, hBs);
848 }
849 
850 double
852 {
853  NS_LOG_FUNCTION (this);
854  NS_UNUSED (a);
855  NS_UNUSED (b);
856  double shadowingStd;
857 
858  if (cond == ChannelCondition::LosConditionValue::LOS)
859  {
860  shadowingStd = 4.0;
861  }
862  else if (cond == ChannelCondition::LosConditionValue::NLOS)
863  {
864  shadowingStd = 7.82;
865  }
866  else
867  {
868  NS_FATAL_ERROR ("Unknown channel condition");
869  }
870 
871  return shadowingStd;
872 }
873 
874 double
876 {
877  NS_LOG_FUNCTION (this);
878  double correlationDistance;
879 
880  // See 3GPP TR 38.901, Table 7.5-6
881  if (cond == ChannelCondition::LosConditionValue::LOS)
882  {
883  correlationDistance = 10;
884  }
885  else if (cond == ChannelCondition::LosConditionValue::NLOS)
886  {
887  correlationDistance = 13;
888  }
889  else
890  {
891  NS_FATAL_ERROR ("Unknown channel condition");
892  }
893 
894  return correlationDistance;
895 }
896 
897 // ------------------------------------------------------------------------- //
898 
900 
901 TypeId
903 {
904  static TypeId tid = TypeId ("ns3::ThreeGppIndoorOfficePropagationLossModel")
906  .SetGroupName ("Propagation")
907  .AddConstructor<ThreeGppIndoorOfficePropagationLossModel> ()
908  ;
909  return tid;
910 }
913 {
914  NS_LOG_FUNCTION (this);
915 
916  // set a default channel condition model
917  m_channelConditionModel = CreateObject<ThreeGppIndoorOpenOfficeChannelConditionModel> ();
918 }
919 
921 {
922  NS_LOG_FUNCTION (this);
923 }
924 
925 double
926 ThreeGppIndoorOfficePropagationLossModel::GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const
927 {
928  NS_LOG_FUNCTION (this);
929  NS_UNUSED (distance2D);
930  NS_UNUSED (distance3D);
931  NS_UNUSED (hUt);
932  NS_UNUSED (hBs);
933 
934  // check if the distace is outside the validity range
935  if (distance3D < 1.0 || distance3D > 150.0)
936  {
937  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
938  }
939 
940  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
941  double loss = 32.4 + 17.3 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9);
942 
943  NS_LOG_DEBUG ("Loss " << loss);
944 
945  return loss;
946 }
947 
948 double
949 ThreeGppIndoorOfficePropagationLossModel::GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const
950 {
951  NS_LOG_FUNCTION (this);
952 
953  // check if the distace is outside the validity range
954  if (distance3D < 1.0 || distance3D > 150.0)
955  {
956  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
957  }
958 
959  // compute the pathloss
960  double plNlos = 17.3 + 38.3 * log10 (distance3D) + 24.9 * log10 (m_frequency / 1e9);
961  double loss = std::max (GetLossLos (distance2D, distance3D, hUt, hBs), plNlos);
962 
963  NS_LOG_DEBUG ("Loss " << loss);
964 
965  return loss;
966 }
967 
968 double
970 {
971  NS_LOG_FUNCTION (this);
972  NS_UNUSED (a);
973  NS_UNUSED (b);
974  double shadowingStd;
975 
976  if (cond == ChannelCondition::LosConditionValue::LOS)
977  {
978  shadowingStd = 3.0;
979  }
980  else if (cond == ChannelCondition::LosConditionValue::NLOS)
981  {
982  shadowingStd = 8.03;
983  }
984  else
985  {
986  NS_FATAL_ERROR ("Unknown channel condition");
987  }
988 
989  return shadowingStd;
990 }
991 
992 double
994 {
995  NS_LOG_FUNCTION (this);
996 
997  // See 3GPP TR 38.901, Table 7.5-6
998  double correlationDistance;
999 
1000  if (cond == ChannelCondition::LosConditionValue::LOS)
1001  {
1002  correlationDistance = 10;
1003  }
1004  else if (cond == ChannelCondition::LosConditionValue::NLOS)
1005  {
1006  correlationDistance = 6;
1007  }
1008  else
1009  {
1010  NS_FATAL_ERROR ("Unknown channel condition");
1011  }
1012 
1013  return correlationDistance;
1014 }
1015 
1016 } // namespace ns3
std::unordered_map< uint32_t, ShadowingMapItem > m_shadowingMap
map to store the shadowing values
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the UMi-Street Canyon scen...
Ptr< ChannelConditionModel > m_channelConditionModel
pointer to the channel condition model
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
virtual int64_t DoAssignStreams(int64_t stream) override
If this model uses objects of type RandomVariableStream, set the stream numbers to the integers start...
AttributeValue implementation for Boolean.
Definition: boolean.h:36
virtual double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const =0
Returns the shadow fading correlation distance.
uint32_t GetId(void) const
Definition: node.cc:109
uint32_t GetInteger(uint32_t min, uint32_t max)
Get the next random value, as an unsigned integer in the specified range .
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
#define min(a, b)
Definition: 80211b.c:42
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.
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:85
virtual double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
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.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
virtual double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
static double GetBpDistance(double frequency, double hA, double hB)
Computes the breakpoint distance for the RMa scenario.
virtual ~ThreeGppUmaPropagationLossModel() override
Destructor.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
virtual double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
virtual 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.901.
static TypeId GetTypeId(void)
Get the type ID.
double GetBpDistance(double hUt, double hBs, double distance2D) const
Computes the breakpoint distance.
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 GetBpDistance(double hUt, double hBs, double distance2D) const
Computes the breakpoint distance.
virtual double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
static double Calculate2dDistance(Vector a, Vector b)
Computes the 2D distance between two 3D vectors.
virtual double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
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:227
#define max(a, b)
Definition: 80211b.c:43
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.
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the RMa scenario...
double CalculateDistance(const Vector3D &a, const Vector3D &b)
Definition: vector.cc:92
double GetFrequency(void) const
Return the current central frequency.
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 m_w
average street width in meters
Define a struct for the m_shadowingMap entries.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
double f(double x, void *params)
Definition: 80211b.c:70
a 2d vector
Definition: vector.h:168
virtual double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Hold objects of type Ptr<T>.
Definition: pointer.h:36
virtual void DoDispose() override
Destructor implementation.
virtual 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 GetValue(double min, double max)
Get the next random value, as a double in the specified range .
static Vector GetVectorDifference(Ptr< MobilityModel > a, Ptr< MobilityModel > b)
Get the difference between the node position.
double GetShadowing(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const
Retrieves the shadowing value by looking at m_shadowingMap.
static double Pl1(double frequency, double distance3D, double h, double w)
Computes the PL1 formula for the RMa scenario.
#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:88
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:42
Vector GetPosition(void) const
static TypeId GetTypeId(void)
Get the type ID.
Ptr< ChannelConditionModel > GetChannelConditionModel(void) const
Returns the associated channel condition model.
Models the propagation loss through a transmission medium.
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
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.
void SetFrequency(double f)
Set the central frequency of the model.
A network Node.
Definition: node.h:56
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
void SetChannelConditionModel(Ptr< ChannelConditionModel > model)
Set the channel condition model used to determine the channel state (e.g., the LOS/NLOS condition) ...
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
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 m_frequency
operating frequency in Hz
virtual double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
virtual double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
Base class for the 3GPP propagation models.
virtual int64_t DoAssignStreams(int64_t stream) override
If this model uses objects of type RandomVariableStream, set the stream numbers to the integers start...
virtual 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 m_h
average building height in meters
static TypeId GetTypeId(void)
Get the type ID.
static uint32_t GetKey(Ptr< MobilityModel > a, Ptr< MobilityModel > b)
Returns an unique key for the channel between a and b.
LosConditionValue
Possible values for Line-of-Sight condition.
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
virtual std::pair< double, double > GetUtAndBsHeights(double za, double zb) const
Determines hUT and hBS.
a unique identifier for an interface.
Definition: type-id.h:58
Ptr< UniformRandomVariable > m_uniformVar
a uniform random variable used for the computation of the breakpoint distance
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the UMa scenario...
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
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.
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the Indoor Office scenario...
static const double M_C
double GetLength() const
Compute the length (magnitude) of the vector.
Definition: vector.cc:85
virtual ~ThreeGppPropagationLossModel() override
Destructor.
virtual ~ThreeGppRmaPropagationLossModel() override
Destructor.
virtual double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const =0
Returns the shadow fading standard deviation.
Ptr< NormalRandomVariable > m_normRandomVariable
normal random variable