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;
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, [[maybe_unused]] double w)
484 {
485  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;
486  return loss;
487 }
488 
489 double
490 ThreeGppRmaPropagationLossModel::GetBpDistance (double frequency, double hA, double hB)
491 {
492  double distanceBp = 2.0 * M_PI * hA * hB * frequency / M_C;
493  return distanceBp;
494 }
495 
496 // ------------------------------------------------------------------------- //
497 
499 
500 TypeId
502 {
503  static TypeId tid = TypeId ("ns3::ThreeGppUmaPropagationLossModel")
505  .SetGroupName ("Propagation")
506  .AddConstructor<ThreeGppUmaPropagationLossModel> ()
507  ;
508  return tid;
509 }
510 
513 {
514  NS_LOG_FUNCTION (this);
515  m_uniformVar = CreateObject<UniformRandomVariable> ();
516 
517  // set a default channel condition model
518  m_channelConditionModel = CreateObject<ThreeGppUmaChannelConditionModel> ();
519 }
520 
522 {
523  NS_LOG_FUNCTION (this);
524 }
525 
526 double
527 ThreeGppUmaPropagationLossModel::GetBpDistance (double hUt, double hBs, double distance2D) const
528 {
529  NS_LOG_FUNCTION (this);
530 
531  // compute g (d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
532  double g = 0.0;
533  if (distance2D > 18.0)
534  {
535  g = 5.0 / 4.0 * pow (distance2D / 100.0, 3) * exp (-distance2D / 150.0);
536  }
537 
538  // compute C (hUt, d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
539  double c = 0.0;
540  if (hUt >= 13.0)
541  {
542  c = pow ((hUt - 13.0) / 10.0, 1.5) * g;
543  }
544 
545  // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
546  double prob = 1.0 / (1.0 + c);
547  double hE = 0.0;
548  if (m_uniformVar->GetValue () < prob)
549  {
550  hE = 1.0;
551  }
552  else
553  {
554  int random = m_uniformVar->GetInteger (12, (int)(hUt - 1.5));
555  hE = (double)floor (random / 3.0) * 3.0;
556  }
557 
558  // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
559  double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
560 
561  return distanceBp;
562 }
563 
564 double
565 ThreeGppUmaPropagationLossModel::GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const
566 {
567  NS_LOG_FUNCTION (this);
568 
569  // check if hBS and hUT are within the validity range
570  if (hUt < 1.5 || hUt > 22.5)
571  {
572  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)");
573  }
574 
575  if (hBs != 25.0)
576  {
577  NS_LOG_WARN ("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
578  }
579 
580  // NOTE The model is intended to be used for BS-UT links, however we may need to
581  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
582  // interference. In order to apply the model, we need to retrieve the values of
583  // hBS and hUT, but in these cases one of the two falls outside the validity
584  // range and the warning message is printed (hBS for the UT-UT case and hUT
585  // for the BS-BS case).
586 
587  // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
588  double distanceBp = GetBpDistance (hUt, hBs, distance2D);
589  NS_LOG_DEBUG ("breakpoint distance " << distanceBp);
590 
591  // check if the distance is outside the validity range
592  if (distance2D < 10.0 || distance2D > 5.0e3)
593  {
594  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
595  }
596 
597  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
598  double loss = 0;
599  if (distance2D <= distanceBp)
600  {
601  // use PL1
602  loss = 28.0 + 22.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9);
603  }
604  else
605  {
606  // use PL2
607  loss = 28.0 + 40.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9) - 9.0 * log10 (pow (distanceBp, 2) + pow (hBs - hUt, 2));
608  }
609 
610  NS_LOG_DEBUG ("Loss " << loss);
611 
612  return loss;
613 }
614 
615 double
616 ThreeGppUmaPropagationLossModel::GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const
617 {
618  NS_LOG_FUNCTION (this);
619 
620  // check if hBS and hUT are within the vaalidity range
621  if (hUt < 1.5 || hUt > 22.5)
622  {
623  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)");
624  }
625 
626  if (hBs != 25.0)
627  {
628  NS_LOG_WARN ("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
629  }
630 
631  // NOTE The model is intended to be used for BS-UT links, however we may need to
632  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
633  // interference. In order to apply the model, we need to retrieve the values of
634  // hBS and hUT, but in these cases one of the two falls outside the validity
635  // range and the warning message is printed (hBS for the UT-UT case and hUT
636  // for the BS-BS case).
637 
638  // check if the distance is outside the validity range
639  if (distance2D < 10.0 || distance2D > 5.0e3)
640  {
641  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
642  }
643 
644  // compute the pathloss
645  double plNlos = 13.54 + 39.08 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9) - 0.6 * (hUt - 1.5);
646  double loss = std::max (GetLossLos (distance2D, distance3D, hUt, hBs), plNlos);
647  NS_LOG_DEBUG ("Loss " << loss);
648 
649  return loss;
650 }
651 
652 double
654  [[maybe_unused]] Ptr<MobilityModel> b,
656 {
657  NS_LOG_FUNCTION (this);
658  double shadowingStd;
659 
660  if (cond == ChannelCondition::LosConditionValue::LOS)
661  {
662  shadowingStd = 4.0;
663  }
664  else if (cond == ChannelCondition::LosConditionValue::NLOS)
665  {
666  shadowingStd = 6.0;
667  }
668  else
669  {
670  NS_FATAL_ERROR ("Unknown channel condition");
671  }
672 
673  return shadowingStd;
674 }
675 
676 double
678 {
679  NS_LOG_FUNCTION (this);
680  double correlationDistance;
681 
682  // See 3GPP TR 38.901, Table 7.5-6
683  if (cond == ChannelCondition::LosConditionValue::LOS)
684  {
685  correlationDistance = 37;
686  }
687  else if (cond == ChannelCondition::LosConditionValue::NLOS)
688  {
689  correlationDistance = 50;
690  }
691  else
692  {
693  NS_FATAL_ERROR ("Unknown channel condition");
694  }
695 
696  return correlationDistance;
697 }
698 
699 int64_t
701 {
702  NS_LOG_FUNCTION (this);
703 
704  m_normRandomVariable->SetStream (stream);
705  m_uniformVar->SetStream (stream);
706  return 2;
707 }
708 
709 // ------------------------------------------------------------------------- //
710 
712 
713 TypeId
715 {
716  static TypeId tid = TypeId ("ns3::ThreeGppUmiStreetCanyonPropagationLossModel")
718  .SetGroupName ("Propagation")
720  ;
721  return tid;
722 }
725 {
726  NS_LOG_FUNCTION (this);
727 
728  // set a default channel condition model
729  m_channelConditionModel = CreateObject<ThreeGppUmiStreetCanyonChannelConditionModel> ();
730 }
731 
733 {
734  NS_LOG_FUNCTION (this);
735 }
736 
737 double
739  [[maybe_unused]] double distance2D) const
740 {
741  NS_LOG_FUNCTION (this);
742 
743  // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
744  double hE = 1.0;
745 
746  // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
747  double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
748 
749  return distanceBp;
750 }
751 
752 double
753 ThreeGppUmiStreetCanyonPropagationLossModel::GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const
754 {
755  NS_LOG_FUNCTION (this);
756 
757  // check if hBS and hUT are within the validity range
758  if (hUt < 1.5 || hUt >= 10.0)
759  {
760  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");
761  }
762 
763  if (hBs != 10.0)
764  {
765  NS_LOG_WARN ("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
766  }
767 
768  // NOTE The model is intended to be used for BS-UT links, however we may need to
769  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
770  // interference. In order to apply the model, we need to retrieve the values of
771  // hBS and hUT, but in these cases one of the two falls outside the validity
772  // range and the warning message is printed (hBS for the UT-UT case and hUT
773  // for the BS-BS case).
774 
775  // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
776  double distanceBp = GetBpDistance (hUt, hBs, distance2D);
777  NS_LOG_DEBUG ("breakpoint distance " << distanceBp);
778 
779  // check if the distance is outside the validity range
780  if (distance2D < 10.0 || distance2D > 5.0e3)
781  {
782  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
783  }
784 
785  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
786  double loss = 0;
787  if (distance2D <= distanceBp)
788  {
789  // use PL1
790  loss = 32.4 + 21.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9);
791  }
792  else
793  {
794  // use PL2
795  loss = 32.4 + 40.0 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9) - 9.5 * log10 (pow (distanceBp, 2) + pow (hBs - hUt, 2));
796  }
797 
798  NS_LOG_DEBUG ("Loss " << loss);
799 
800  return loss;
801 }
802 
803 double
804 ThreeGppUmiStreetCanyonPropagationLossModel::GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const
805 {
806  NS_LOG_FUNCTION (this);
807 
808  // check if hBS and hUT are within the validity range
809  if (hUt < 1.5 || hUt >= 10.0)
810  {
811  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");
812  }
813 
814  if (hBs != 10.0)
815  {
816  NS_LOG_WARN ("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
817  }
818 
819  // NOTE The model is intended to be used for BS-UT links, however we may need to
820  // compute the pathloss between two BSs or UTs, e.g., to evaluate the
821  // interference. In order to apply the model, we need to retrieve the values of
822  // hBS and hUT, but in these cases one of the two falls outside the validity
823  // range and the warning message is printed (hBS for the UT-UT case and hUT
824  // for the BS-BS case).
825 
826  // check if the distance is outside the validity range
827  if (distance2D < 10.0 || distance2D > 5.0e3)
828  {
829  NS_LOG_WARN ("The 2D distance is outside the validity range, the pathloss value may not be accurate");
830  }
831 
832  // compute the pathloss
833  double plNlos = 22.4 + 35.3 * log10 (distance3D) + 21.3 * log10 (m_frequency / 1e9) - 0.3 * (hUt - 1.5);
834  double loss = std::max (GetLossLos (distance2D, distance3D, hUt, hBs), plNlos);
835  NS_LOG_DEBUG ("Loss " << loss);
836 
837  return loss;
838 }
839 
840 std::pair<double, double>
842 {
843  NS_LOG_FUNCTION (this);
844  // TR 38.901 specifies hBS = 10 m and 1.5 <= hUT <= 22.5
845  double hBs, hUt;
846  if (za == 10.0)
847  {
848  // node A is the BS and node B is the UT
849  hBs = za;
850  hUt = zb;
851  }
852  else if (zb == 10.0)
853  {
854  // node B is the BS and node A is the UT
855  hBs = zb;
856  hUt = za;
857  }
858  else
859  {
860  // We cannot know who is the BS and who is the UT, we assume that the
861  // tallest node is the BS and the smallest is the UT
862  hBs = std::max (za, zb);
863  hUt = std::min (za, za);
864  }
865 
866  return std::pair<double, double> (hUt, hBs);
867 }
868 
869 double
871  [[maybe_unused]] Ptr<MobilityModel> b,
873 {
874  NS_LOG_FUNCTION (this);
875  double shadowingStd;
876 
877  if (cond == ChannelCondition::LosConditionValue::LOS)
878  {
879  shadowingStd = 4.0;
880  }
881  else if (cond == ChannelCondition::LosConditionValue::NLOS)
882  {
883  shadowingStd = 7.82;
884  }
885  else
886  {
887  NS_FATAL_ERROR ("Unknown channel condition");
888  }
889 
890  return shadowingStd;
891 }
892 
893 double
895 {
896  NS_LOG_FUNCTION (this);
897  double correlationDistance;
898 
899  // See 3GPP TR 38.901, Table 7.5-6
900  if (cond == ChannelCondition::LosConditionValue::LOS)
901  {
902  correlationDistance = 10;
903  }
904  else if (cond == ChannelCondition::LosConditionValue::NLOS)
905  {
906  correlationDistance = 13;
907  }
908  else
909  {
910  NS_FATAL_ERROR ("Unknown channel condition");
911  }
912 
913  return correlationDistance;
914 }
915 
916 // ------------------------------------------------------------------------- //
917 
919 
920 TypeId
922 {
923  static TypeId tid = TypeId ("ns3::ThreeGppIndoorOfficePropagationLossModel")
925  .SetGroupName ("Propagation")
926  .AddConstructor<ThreeGppIndoorOfficePropagationLossModel> ()
927  ;
928  return tid;
929 }
932 {
933  NS_LOG_FUNCTION (this);
934 
935  // set a default channel condition model
936  m_channelConditionModel = CreateObject<ThreeGppIndoorOpenOfficeChannelConditionModel> ();
937 }
938 
940 {
941  NS_LOG_FUNCTION (this);
942 }
943 
944 double
945 ThreeGppIndoorOfficePropagationLossModel::GetLossLos ([[maybe_unused]] double distance2D,
946  [[maybe_unused]] double distance3D,
947  [[maybe_unused]] double hUt,
948  [[maybe_unused]] double hBs) const
949 {
950  NS_LOG_FUNCTION (this);
951 
952  // check if the distance is outside the validity range
953  if (distance3D < 1.0 || distance3D > 150.0)
954  {
955  NS_LOG_WARN ("The 3D distance is outside the validity range, the pathloss value may not be accurate");
956  }
957 
958  // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
959  double loss = 32.4 + 17.3 * log10 (distance3D) + 20.0 * log10 (m_frequency / 1e9);
960 
961  NS_LOG_DEBUG ("Loss " << loss);
962 
963  return loss;
964 }
965 
966 double
967 ThreeGppIndoorOfficePropagationLossModel::GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const
968 {
969  NS_LOG_FUNCTION (this);
970 
971  // check if the distance is outside the validity range
972  if (distance3D < 1.0 || distance3D > 150.0)
973  {
974  NS_LOG_WARN ("The 3D distance is outside the validity range, the pathloss value may not be accurate");
975  }
976 
977  // compute the pathloss
978  double plNlos = 17.3 + 38.3 * log10 (distance3D) + 24.9 * log10 (m_frequency / 1e9);
979  double loss = std::max (GetLossLos (distance2D, distance3D, hUt, hBs), plNlos);
980 
981  NS_LOG_DEBUG ("Loss " << loss);
982 
983  return loss;
984 }
985 
986 double
988  [[maybe_unused]] Ptr<MobilityModel> b,
990 {
991  NS_LOG_FUNCTION (this);
992  double shadowingStd;
993 
994  if (cond == ChannelCondition::LosConditionValue::LOS)
995  {
996  shadowingStd = 3.0;
997  }
998  else if (cond == ChannelCondition::LosConditionValue::NLOS)
999  {
1000  shadowingStd = 8.03;
1001  }
1002  else
1003  {
1004  NS_FATAL_ERROR ("Unknown channel condition");
1005  }
1006 
1007  return shadowingStd;
1008 }
1009 
1010 double
1012 {
1013  NS_LOG_FUNCTION (this);
1014 
1015  // See 3GPP TR 38.901, Table 7.5-6
1016  double correlationDistance;
1017 
1018  if (cond == ChannelCondition::LosConditionValue::LOS)
1019  {
1020  correlationDistance = 10;
1021  }
1022  else if (cond == ChannelCondition::LosConditionValue::NLOS)
1023  {
1024  correlationDistance = 6;
1025  }
1026  else
1027  {
1028  NS_FATAL_ERROR ("Unknown channel condition");
1029  }
1030 
1031  return correlationDistance;
1032 }
1033 
1034 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
double f(double x, void *params)
Definition: 80211b.c:70
#define max(a, b)
Definition: 80211b.c:43
AttributeValue implementation for Boolean.
Definition: boolean.h:37
LosConditionValue
Possible values for Line-of-Sight condition.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
Vector GetPosition(void) const
A network Node.
Definition: node.h:57
uint32_t GetId(void) const
Definition: node.cc:109
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
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:74
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...
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.
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.
double GetLoss(Ptr< ChannelCondition > cond, double distance2D, double distance3D, double hUt, double hBs) const
Computes the pathloss between a and b.
Ptr< ChannelConditionModel > GetChannelConditionModel(void) const
Returns the associated channel condition model.
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)
static TypeId GetTypeId(void)
Get the type ID.
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 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
virtual ~ThreeGppPropagationLossModel() override
Destructor.
double GetFrequency(void) const
Return the current central frequency.
void SetFrequency(double f)
Set the central frequency of the model.
virtual 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.
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.
virtual std::pair< double, double > GetUtAndBsHeights(double za, double zb) const
Determines hUT and hBS.
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....
static Vector GetVectorDifference(Ptr< MobilityModel > a, Ptr< MobilityModel > b)
Get the difference between the node position.
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the RMa scenario.
virtual 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.
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.
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.
virtual ~ThreeGppRmaPropagationLossModel() override
Destructor.
virtual double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
double m_h
average building height in meters
static double GetBpDistance(double frequency, double hA, double hB)
Computes the breakpoint distance for the RMa scenario.
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the UMa scenario.
double GetLossLos(double distance2D, double distance3D, double hUt, double hBs) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetBpDistance(double hUt, double hBs, double distance2D) const
Computes the breakpoint distance.
virtual ~ThreeGppUmaPropagationLossModel() override
Destructor.
virtual 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.
Ptr< UniformRandomVariable > m_uniformVar
a uniform random variable used for the computation of the breakpoint distance
virtual double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
virtual 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.
virtual 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 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.
virtual 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:922
double GetValue(double min, double max)
Get the next random value, as a double in the specified range .
uint32_t GetInteger(uint32_t min, uint32_t max)
Get the next random value, as an unsigned integer in the specified range .
a 2d vector
Definition: vector.h:183
double GetLength() const
Compute the length (magnitude) of the vector.
Definition: vector.cc:85
#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 AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
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
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
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 NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#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:265
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static const double M_C
propagation velocity in free space
double CalculateDistance(const Vector3D &a, const Vector3D &b)
Definition: vector.cc:105
list x
Random number samples.