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
31namespace ns3 {
32
33NS_LOG_COMPONENT_DEFINE ("ThreeGppPropagationLossModel");
34
35static const double M_C = 3.0e8;
36
37// ------------------------------------------------------------------------- //
38
40
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
81void
83{
84 m_channelConditionModel->Dispose ();
86 m_shadowingMap.clear ();
87}
88
89void
91{
92 NS_LOG_FUNCTION (this);
94}
95
98{
99 NS_LOG_FUNCTION (this);
101}
102
103void
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
111double
113{
114 NS_LOG_FUNCTION (this);
115 return m_frequency;
116}
117
118double
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
145 {
146 rxPow -= GetShadowing (a, b, cond->GetLosCondition ());
147 }
148
149 return rxPow;
150}
151
152double
153ThreeGppPropagationLossModel::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
177double
178ThreeGppPropagationLossModel::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
185double
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
236std::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
247int64_t
249{
250 NS_LOG_FUNCTION (this);
251
252 m_normRandomVariable->SetStream (stream);
253 return 1;
254}
255
256double
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
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
280Vector
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
300TypeId
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
333double
334ThreeGppRmaPropagationLossModel::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
384double
385ThreeGppRmaPropagationLossModel::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
424double
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
459double
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
482double
483ThreeGppRmaPropagationLossModel::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
489double
490ThreeGppRmaPropagationLossModel::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
500TypeId
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
526double
527ThreeGppUmaPropagationLossModel::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
564double
565ThreeGppUmaPropagationLossModel::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
615double
616ThreeGppUmaPropagationLossModel::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
652double
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
676double
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
699int64_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
713TypeId
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
737double
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
752double
753ThreeGppUmiStreetCanyonPropagationLossModel::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
803double
804ThreeGppUmiStreetCanyonPropagationLossModel::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
840std::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
869double
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
893double
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
920TypeId
922{
923 static TypeId tid = TypeId ("ns3::ThreeGppIndoorOfficePropagationLossModel")
925 .SetGroupName ("Propagation")
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
944double
945ThreeGppIndoorOfficePropagationLossModel::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
966double
967ThreeGppIndoorOfficePropagationLossModel::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
986double
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
1010double
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)
Definition: boolean.h:85
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:42
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
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.