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  rxPow -= GetLoss (cond, distance2d, distance3d, heights.first, heights.second);
143 
144  if (m_shadowingEnabled)
145  {
146  rxPow -= GetShadowing (a, b, cond->GetLosCondition ());
147  }
148 
149  return rxPow;
150 }
151 
152 double
153 ThreeGppPropagationLossModel::GetLoss (Ptr<ChannelCondition> cond, double distance2d, double distance3d, double hUt, double hBs) const
154 {
155  NS_LOG_FUNCTION (this);
156 
157  double loss = 0;
158  if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::LOS)
159  {
160  loss = GetLossLos (distance2d, distance3d, hUt, hBs);
161  }
162  else if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::NLOSv)
163  {
164  loss = GetLossNlosv (distance2d, distance3d, hUt, hBs);
165  }
166  else if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::NLOS)
167  {
168  loss = GetLossNlos (distance2d, distance3d, hUt, hBs);
169  }
170  else
171  {
172  NS_FATAL_ERROR ("Unknown channel condition");
173  }
174  return loss;
175 }
176 
177 double
178 ThreeGppPropagationLossModel::GetLossNlosv (double distance2D, double distance3D, double hUt, double hBs) const
179 {
180  NS_LOG_FUNCTION (this);
181  NS_FATAL_ERROR ("Unsupported channel condition (NLOSv)");
182  return 0;
183 }
184 
185 double
187 {
188  NS_LOG_FUNCTION (this);
189 
190  double shadowingValue;
191 
192  // compute the channel key
193  uint32_t key = GetKey (a, b);
194 
195  bool notFound = false; // indicates if the shadowing value has not been computed yet
196  bool newCondition = false; // indicates if the channel condition has changed
197  Vector newDistance; // the distance vector, that is not a distance but a difference
198  auto it = m_shadowingMap.end (); // the shadowing map iterator
199  if (m_shadowingMap.find (key) != m_shadowingMap.end ())
200  {
201  // found the shadowing value in the map
202  it = m_shadowingMap.find (key);
203  newDistance = GetVectorDifference (a, b);
204  newCondition = (it->second.m_condition != cond); // true if the condition changed
205  }
206  else
207  {
208  notFound = true;
209 
210  // add a new entry in the map and update the iterator
211  ShadowingMapItem newItem;
212  it = m_shadowingMap.insert (it, std::make_pair (key, newItem));
213  }
214 
215  if (notFound || newCondition)
216  {
217  // generate a new independent realization
218  shadowingValue = m_normRandomVariable->GetValue () * GetShadowingStd (a, b, cond);
219  }
220  else
221  {
222  // compute a new correlated shadowing loss
223  Vector2D displacement (newDistance.x - it->second.m_distance.x, newDistance.y - it->second.m_distance.y);
224  double R = exp (-1 * displacement.GetLength () / GetShadowingCorrelationDistance (cond));
225  shadowingValue = R * it->second.m_shadowing + sqrt (1 - R * R) * m_normRandomVariable->GetValue () * GetShadowingStd (a, b, cond);
226  }
227 
228  // update the entry in the map
229  it->second.m_shadowing = shadowingValue;
230  it->second.m_distance = newDistance; // Save the (0,0,0) vector in case it's the first time we are calculating this value
231  it->second.m_condition = cond;
232 
233  return shadowingValue;
234 }
235 
236 std::pair<double, double>
238 {
239  // The default implementation assumes that the tallest node is the BS and the
240  // smallest is the UT.
241  double hUt = std::min (za, zb);
242  double hBs = std::max (za, zb);
243 
244  return std::pair<double, double> (hUt, hBs);
245 }
246 
247 int64_t
249 {
250  NS_LOG_FUNCTION (this);
251 
252  m_normRandomVariable->SetStream (stream);
253  return 1;
254 }
255 
256 double
258 {
259  double x = a.x - b.x;
260  double y = a.y - b.y;
261  double distance2D = sqrt (x * x + y * y);
262 
263  return distance2D;
264 }
265 
266 uint32_t
268 {
269  // use the nodes ids to obtain an unique key for the channel between a and b
270  // sort the nodes ids so that the key is reciprocal
271  uint32_t x1 = std::min (a->GetObject<Node> ()->GetId (), b->GetObject<Node> ()->GetId ());
272  uint32_t x2 = std::max (a->GetObject<Node> ()->GetId (), b->GetObject<Node> ()->GetId ());
273 
274  // use the cantor function to obtain the key
275  uint32_t key = (((x1 + x2) * (x1 + x2 + 1)) / 2) + x2;
276 
277  return key;
278 }
279 
280 Vector
282 {
283  uint32_t x1 = a->GetObject<Node> ()->GetId ();
284  uint32_t x2 = b->GetObject<Node> ()->GetId ();
285 
286  if (x1 < x2)
287  {
288  return b->GetPosition () - a->GetPosition ();
289  }
290  else
291  {
292  return a->GetPosition () - b->GetPosition ();
293  }
294 }
295 
296 // ------------------------------------------------------------------------- //
297 
299 
300 TypeId
302 {
303  static TypeId tid = TypeId ("ns3::ThreeGppRmaPropagationLossModel")
305  .SetGroupName ("Propagation")
306  .AddConstructor<ThreeGppRmaPropagationLossModel> ()
307  .AddAttribute ("AvgBuildingHeight", "The average building height in meters.",
308  DoubleValue (5.0),
310  MakeDoubleChecker<double> (5.0, 50.0))
311  .AddAttribute ("AvgStreetWidth", "The average street width in meters.",
312  DoubleValue (20.0),
314  MakeDoubleChecker<double> (5.0, 50.0))
315  ;
316  return tid;
317 }
318 
321 {
322  NS_LOG_FUNCTION (this);
323 
324  // set a default channel condition model
325  m_channelConditionModel = CreateObject<ThreeGppRmaChannelConditionModel> ();
326 }
327 
329 {
330  NS_LOG_FUNCTION (this);
331 }
332 
333 double
334 ThreeGppRmaPropagationLossModel::GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const
335 {
336  NS_LOG_FUNCTION (this);
337  NS_ASSERT_MSG (m_frequency <= 30.0e9, "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
338 
339  // check if hBS and hUT are within the specified validity range
340  if (hUt < 1.0 || hUt > 10.0)
341  {
342  NS_LOG_WARN ("The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
343  }
344 
345  if (hBs < 10.0 || hBs > 150.0)
346  {
347  NS_LOG_WARN ("The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
348  }
349 
350  // NOTE The model is intended to be used for BS-UT links, however we may need to
351  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
352  // interference. In order to apply the model, we need to retrieve the values of
353  // hBS and hUT, but in these cases one of the two falls outside the validity
354  // range and the warning message is printed (hBS for the UT-UT case and hUT
355  // for the BS-BS case).
356 
357  double distanceBp = GetBpDistance (m_frequency, hBs, hUt);
358  NS_LOG_DEBUG ("breakpoint distance " << distanceBp);
359 
360  // check if the distance is outside the validity range
361  if (distance2D < 10.0 || distance2D > 10.0e3)
362  {
363  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
364  }
365 
366  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
367  double loss = 0;
368  if (distance2D <= distanceBp)
369  {
370  // use PL1
371  loss = Pl1 (m_frequency, distance3D, m_h, m_w);
372  }
373  else
374  {
375  // use PL2
376  loss = Pl1 (m_frequency, distanceBp, m_h, m_w) + 40 * log10 (distance3D / distanceBp);
377  }
378 
379  NS_LOG_DEBUG ("Loss " << loss);
380 
381  return loss;
382 }
383 
384 double
385 ThreeGppRmaPropagationLossModel::GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const
386 {
387  NS_LOG_FUNCTION (this);
388  NS_ASSERT_MSG (m_frequency <= 30.0e9, "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
389 
390  // check if hBs and hUt are within the validity range
391  if (hUt < 1.0 || hUt > 10.0)
392  {
393  NS_LOG_WARN ("The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
394  }
395 
396  if (hBs < 10.0 || hBs > 150.0)
397  {
398  NS_LOG_WARN ("The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
399  }
400 
401  // NOTE The model is intended to be used for BS-UT links, however we may need to
402  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
403  // interference. In order to apply the model, we need to retrieve the values of
404  // hBS and hUT, but in these cases one of the two falls outside the validity
405  // range and the warning message is printed (hBS for the UT-UT case and hUT
406  // for the BS-BS case).
407 
408  // check if the distance is outside the validity range
409  if (distance2D < 10.0 || distance2D > 5.0e3)
410  {
411  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
412  }
413 
414  // compute the pathloss
415  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);
416 
417  double loss = std::max (GetLossLos (distance2D, distance3D, hUt, hBs), plNlos);
418 
419  NS_LOG_DEBUG ("Loss " << loss);
420 
421  return loss;
422 }
423 
424 double
426 {
427  NS_LOG_FUNCTION (this);
428  double shadowingStd;
429 
430  if (cond == ChannelCondition::LosConditionValue::LOS)
431  {
432  // compute the 2D distance between the two nodes
433  double distance2d = Calculate2dDistance (a->GetPosition (), b->GetPosition ());
434 
435  // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 5)
436  double distanceBp = GetBpDistance (m_frequency, a->GetPosition ().z, b->GetPosition ().z);
437 
438  if (distance2d <= distanceBp)
439  {
440  shadowingStd = 4.0;
441  }
442  else
443  {
444  shadowingStd = 6.0;
445  }
446  }
447  else if (cond == ChannelCondition::LosConditionValue::NLOS)
448  {
449  shadowingStd = 8.0;
450  }
451  else
452  {
453  NS_FATAL_ERROR ("Unknown channel condition");
454  }
455 
456  return shadowingStd;
457 }
458 
459 double
461 {
462  NS_LOG_FUNCTION (this);
463  double correlationDistance;
464 
465  // See 3GPP TR 38.901, Table 7.5-6
466  if (cond == ChannelCondition::LosConditionValue::LOS)
467  {
468  correlationDistance = 37;
469  }
470  else if (cond == ChannelCondition::LosConditionValue::NLOS)
471  {
472  correlationDistance = 120;
473  }
474  else
475  {
476  NS_FATAL_ERROR ("Unknown channel condition");
477  }
478 
479  return correlationDistance;
480 }
481 
482 double
483 ThreeGppRmaPropagationLossModel::Pl1 (double frequency, double distance3D, double h, double w)
484 {
485  NS_UNUSED (w);
486  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;
487  return loss;
488 }
489 
490 double
491 ThreeGppRmaPropagationLossModel::GetBpDistance (double frequency, double hA, double hB)
492 {
493  double distanceBp = 2.0 * M_PI * hA * hB * frequency / M_C;
494  return distanceBp;
495 }
496 
497 // ------------------------------------------------------------------------- //
498 
500 
501 TypeId
503 {
504  static TypeId tid = TypeId ("ns3::ThreeGppUmaPropagationLossModel")
506  .SetGroupName ("Propagation")
507  .AddConstructor<ThreeGppUmaPropagationLossModel> ()
508  ;
509  return tid;
510 }
511 
514 {
515  NS_LOG_FUNCTION (this);
516  m_uniformVar = CreateObject<UniformRandomVariable> ();
517 
518  // set a default channel condition model
519  m_channelConditionModel = CreateObject<ThreeGppUmaChannelConditionModel> ();
520 }
521 
523 {
524  NS_LOG_FUNCTION (this);
525 }
526 
527 double
528 ThreeGppUmaPropagationLossModel::GetBpDistance (double hUt, double hBs, double distance2D) const
529 {
530  NS_LOG_FUNCTION (this);
531 
532  // compute g (d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
533  double g = 0.0;
534  if (distance2D > 18.0)
535  {
536  g = 5.0 / 4.0 * pow (distance2D / 100.0, 3) * exp (-distance2D / 150.0);
537  }
538 
539  // compute C (hUt, d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
540  double c = 0.0;
541  if (hUt >= 13.0)
542  {
543  c = pow ((hUt - 13.0) / 10.0, 1.5) * g;
544  }
545 
546  // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
547  double prob = 1.0 / (1.0 + c);
548  double hE = 0.0;
549  if (m_uniformVar->GetValue () < prob)
550  {
551  hE = 1.0;
552  }
553  else
554  {
555  int random = m_uniformVar->GetInteger (12, (int)(hUt - 1.5));
556  hE = (double)floor (random / 3.0) * 3.0;
557  }
558 
559  // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
560  double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
561 
562  return distanceBp;
563 }
564 
565 double
566 ThreeGppUmaPropagationLossModel::GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const
567 {
568  NS_LOG_FUNCTION (this);
569 
570  // check if hBS and hUT are within the validity range
571  if (hUt < 1.5 || hUt > 22.5)
572  {
573  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)");
574  }
575 
576  if (hBs != 25.0)
577  {
578  NS_LOG_WARN ("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
579  }
580 
581  // NOTE The model is intended to be used for BS-UT links, however we may need to
582  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
583  // interference. In order to apply the model, we need to retrieve the values of
584  // hBS and hUT, but in these cases one of the two falls outside the validity
585  // range and the warning message is printed (hBS for the UT-UT case and hUT
586  // for the BS-BS case).
587 
588  // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
589  double distanceBp = GetBpDistance (hUt, hBs, distance2D);
590  NS_LOG_DEBUG ("breakpoint distance " << distanceBp);
591 
592  // check if the distance is outside the validity range
593  if (distance2D < 10.0 || distance2D > 5.0e3)
594  {
595  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
596  }
597 
598  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
599  double loss = 0;
600  if (distance2D <= distanceBp)
601  {
602  // use PL1
603  loss = 28.0 + 22.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9);
604  }
605  else
606  {
607  // use PL2
608  loss = 28.0 + 40.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9) - 9.0 * log10 (pow (distanceBp, 2) + pow (hBs - hUt, 2));
609  }
610 
611  NS_LOG_DEBUG ("Loss " << loss);
612 
613  return loss;
614 }
615 
616 double
617 ThreeGppUmaPropagationLossModel::GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const
618 {
619  NS_LOG_FUNCTION (this);
620 
621  // check if hBS and hUT are within the vaalidity range
622  if (hUt < 1.5 || hUt > 22.5)
623  {
624  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)");
625  }
626 
627  if (hBs != 25.0)
628  {
629  NS_LOG_WARN ("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
630  }
631 
632  // NOTE The model is intended to be used for BS-UT links, however we may need to
633  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
634  // interference. In order to apply the model, we need to retrieve the values of
635  // hBS and hUT, but in these cases one of the two falls outside the validity
636  // range and the warning message is printed (hBS for the UT-UT case and hUT
637  // for the BS-BS case).
638 
639  // check if the distance is outside the validity range
640  if (distance2D < 10.0 || distance2D > 5.0e3)
641  {
642  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
643  }
644 
645  // compute the pathloss
646  double plNlos = 13.54 + 39.08 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9) - 0.6 * (hUt - 1.5);
647  double loss = std::max (GetLossLos (distance2D, distance3D, hUt, hBs), plNlos);
648  NS_LOG_DEBUG ("Loss " << loss);
649 
650  return loss;
651 }
652 
653 double
655 {
656  NS_LOG_FUNCTION (this);
657  NS_UNUSED (a);
658  NS_UNUSED (b);
659  double shadowingStd;
660 
661  if (cond == ChannelCondition::LosConditionValue::LOS)
662  {
663  shadowingStd = 4.0;
664  }
665  else if (cond == ChannelCondition::LosConditionValue::NLOS)
666  {
667  shadowingStd = 6.0;
668  }
669  else
670  {
671  NS_FATAL_ERROR ("Unknown channel condition");
672  }
673 
674  return shadowingStd;
675 }
676 
677 double
679 {
680  NS_LOG_FUNCTION (this);
681  double correlationDistance;
682 
683  // See 3GPP TR 38.901, Table 7.5-6
684  if (cond == ChannelCondition::LosConditionValue::LOS)
685  {
686  correlationDistance = 37;
687  }
688  else if (cond == ChannelCondition::LosConditionValue::NLOS)
689  {
690  correlationDistance = 50;
691  }
692  else
693  {
694  NS_FATAL_ERROR ("Unknown channel condition");
695  }
696 
697  return correlationDistance;
698 }
699 
700 int64_t
702 {
703  NS_LOG_FUNCTION (this);
704 
705  m_normRandomVariable->SetStream (stream);
706  m_uniformVar->SetStream (stream);
707  return 2;
708 }
709 
710 // ------------------------------------------------------------------------- //
711 
713 
714 TypeId
716 {
717  static TypeId tid = TypeId ("ns3::ThreeGppUmiStreetCanyonPropagationLossModel")
719  .SetGroupName ("Propagation")
721  ;
722  return tid;
723 }
726 {
727  NS_LOG_FUNCTION (this);
728 
729  // set a default channel condition model
730  m_channelConditionModel = CreateObject<ThreeGppUmiStreetCanyonChannelConditionModel> ();
731 }
732 
734 {
735  NS_LOG_FUNCTION (this);
736 }
737 
738 double
739 ThreeGppUmiStreetCanyonPropagationLossModel::GetBpDistance (double hUt, double hBs, double distance2D) const
740 {
741  NS_LOG_FUNCTION (this);
742  NS_UNUSED (distance2D);
743 
744  // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
745  double hE = 1.0;
746 
747  // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
748  double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
749 
750  return distanceBp;
751 }
752 
753 double
754 ThreeGppUmiStreetCanyonPropagationLossModel::GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const
755 {
756  NS_LOG_FUNCTION (this);
757 
758  // check if hBS and hUT are within the validity range
759  if (hUt < 1.5 || hUt >= 10.0)
760  {
761  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");
762  }
763 
764  if (hBs != 10.0)
765  {
766  NS_LOG_WARN ("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
767  }
768 
769  // NOTE The model is intended to be used for BS-UT links, however we may need to
770  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
771  // interference. In order to apply the model, we need to retrieve the values of
772  // hBS and hUT, but in these cases one of the two falls outside the validity
773  // range and the warning message is printed (hBS for the UT-UT case and hUT
774  // for the BS-BS case).
775 
776  // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
777  double distanceBp = GetBpDistance (hUt, hBs, distance2D);
778  NS_LOG_DEBUG ("breakpoint distance " << distanceBp);
779 
780  // check if the distance is outside the validity range
781  if (distance2D < 10.0 || distance2D > 5.0e3)
782  {
783  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
784  }
785 
786  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
787  double loss = 0;
788  if (distance2D <= distanceBp)
789  {
790  // use PL1
791  loss = 32.4 + 21.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9);
792  }
793  else
794  {
795  // use PL2
796  loss = 32.4 + 40.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9) - 9.5 * log10 (pow (distanceBp, 2) + pow (hBs - hUt, 2));
797  }
798 
799  NS_LOG_DEBUG ("Loss " << loss);
800 
801  return loss;
802 }
803 
804 double
805 ThreeGppUmiStreetCanyonPropagationLossModel::GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const
806 {
807  NS_LOG_FUNCTION (this);
808 
809  // check if hBS and hUT are within the validity range
810  if (hUt < 1.5 || hUt >= 10.0)
811  {
812  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");
813  }
814 
815  if (hBs != 10.0)
816  {
817  NS_LOG_WARN ("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
818  }
819 
820  // NOTE The model is intended to be used for BS-UT links, however we may need to
821  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
822  // interference. In order to apply the model, we need to retrieve the values of
823  // hBS and hUT, but in these cases one of the two falls outside the validity
824  // range and the warning message is printed (hBS for the UT-UT case and hUT
825  // for the BS-BS case).
826 
827  // check if the distance is outside the validity range
828  if (distance2D < 10.0 || distance2D > 5.0e3)
829  {
830  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
831  }
832 
833  // compute the pathloss
834  double plNlos = 22.4 + 35.3 * log10 (distance3D) + 21.3 * log10 (m_frequency / 1e9) - 0.3 * (hUt - 1.5);
835  double loss = std::max (GetLossLos (distance2D, distance3D, hUt, hBs), plNlos);
836  NS_LOG_DEBUG ("Loss " << loss);
837 
838  return loss;
839 }
840 
841 std::pair<double, double>
843 {
844  NS_LOG_FUNCTION (this);
845  // TR 38.901 specifies hBS = 10 m and 1.5 <= hUT <= 22.5
846  double hBs, hUt;
847  if (za == 10.0)
848  {
849  // node A is the BS and node B is the UT
850  hBs = za;
851  hUt = zb;
852  }
853  else if (zb == 10.0)
854  {
855  // node B is the BS and node A is the UT
856  hBs = zb;
857  hUt = za;
858  }
859  else
860  {
861  // We cannot know who is the BS and who is the UT, we assume that the
862  // tallest node is the BS and the smallest is the UT
863  hBs = std::max (za, zb);
864  hUt = std::min (za, za);
865  }
866 
867  return std::pair<double, double> (hUt, hBs);
868 }
869 
870 double
872 {
873  NS_LOG_FUNCTION (this);
874  NS_UNUSED (a);
875  NS_UNUSED (b);
876  double shadowingStd;
877 
878  if (cond == ChannelCondition::LosConditionValue::LOS)
879  {
880  shadowingStd = 4.0;
881  }
882  else if (cond == ChannelCondition::LosConditionValue::NLOS)
883  {
884  shadowingStd = 7.82;
885  }
886  else
887  {
888  NS_FATAL_ERROR ("Unknown channel condition");
889  }
890 
891  return shadowingStd;
892 }
893 
894 double
896 {
897  NS_LOG_FUNCTION (this);
898  double correlationDistance;
899 
900  // See 3GPP TR 38.901, Table 7.5-6
901  if (cond == ChannelCondition::LosConditionValue::LOS)
902  {
903  correlationDistance = 10;
904  }
905  else if (cond == ChannelCondition::LosConditionValue::NLOS)
906  {
907  correlationDistance = 13;
908  }
909  else
910  {
911  NS_FATAL_ERROR ("Unknown channel condition");
912  }
913 
914  return correlationDistance;
915 }
916 
917 // ------------------------------------------------------------------------- //
918 
920 
921 TypeId
923 {
924  static TypeId tid = TypeId ("ns3::ThreeGppIndoorOfficePropagationLossModel")
926  .SetGroupName ("Propagation")
927  .AddConstructor<ThreeGppIndoorOfficePropagationLossModel> ()
928  ;
929  return tid;
930 }
933 {
934  NS_LOG_FUNCTION (this);
935 
936  // set a default channel condition model
937  m_channelConditionModel = CreateObject<ThreeGppIndoorOpenOfficeChannelConditionModel> ();
938 }
939 
941 {
942  NS_LOG_FUNCTION (this);
943 }
944 
945 double
946 ThreeGppIndoorOfficePropagationLossModel::GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const
947 {
948  NS_LOG_FUNCTION (this);
949  NS_UNUSED (distance2D);
950  NS_UNUSED (distance3D);
951  NS_UNUSED (hUt);
952  NS_UNUSED (hBs);
953 
954  // check if the distance is outside the validity range
955  if (distance3D < 1.0 || distance3D > 150.0)
956  {
957  NS_LOG_WARN ("The 3D distance is outside the validity range, the pathloss value may not be accurate");
958  }
959 
960  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
961  double loss = 32.4 + 17.3 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9);
962 
963  NS_LOG_DEBUG ("Loss " << loss);
964 
965  return loss;
966 }
967 
968 double
969 ThreeGppIndoorOfficePropagationLossModel::GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const
970 {
971  NS_LOG_FUNCTION (this);
972 
973  // check if the distance is outside the validity range
974  if (distance3D < 1.0 || distance3D > 150.0)
975  {
976  NS_LOG_WARN ("The 3D distance is outside the validity range, the pathloss value may not be accurate");
977  }
978 
979  // compute the pathloss
980  double plNlos = 17.3 + 38.3 * log10 (distance3D) + 24.9 * log10 (m_frequency / 1e9);
981  double loss = std::max (GetLossLos (distance2D, distance3D, hUt, hBs), plNlos);
982 
983  NS_LOG_DEBUG ("Loss " << loss);
984 
985  return loss;
986 }
987 
988 double
990 {
991  NS_LOG_FUNCTION (this);
992  NS_UNUSED (a);
993  NS_UNUSED (b);
994  double shadowingStd;
995 
996  if (cond == ChannelCondition::LosConditionValue::LOS)
997  {
998  shadowingStd = 3.0;
999  }
1000  else if (cond == ChannelCondition::LosConditionValue::NLOS)
1001  {
1002  shadowingStd = 8.03;
1003  }
1004  else
1005  {
1006  NS_FATAL_ERROR ("Unknown channel condition");
1007  }
1008 
1009  return shadowingStd;
1010 }
1011 
1012 double
1014 {
1015  NS_LOG_FUNCTION (this);
1016 
1017  // See 3GPP TR 38.901, Table 7.5-6
1018  double correlationDistance;
1019 
1020  if (cond == ChannelCondition::LosConditionValue::LOS)
1021  {
1022  correlationDistance = 10;
1023  }
1024  else if (cond == ChannelCondition::LosConditionValue::NLOS)
1025  {
1026  correlationDistance = 6;
1027  }
1028  else
1029  {
1030  NS_FATAL_ERROR ("Unknown channel condition");
1031  }
1032 
1033  return correlationDistance;
1034 }
1035 
1036 } // 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
double GetLoss(Ptr< ChannelCondition > cond, double distance2D, double distance3D, double hUt, double hBs) const
Computes the pathloss between a and b.
#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.
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...
#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