From 53217384c99ec9e5ff6eba8d47489381ca2aa79b Mon Sep 17 00:00:00 2001 From: kkoutlia Date: Mon, 27 Feb 2023 12:58:00 +0100 Subject: [PATCH] buildings: Include Low/High building penetration losses --- CHANGES.md | 1 + src/buildings/doc/source/buildings-user.rst | 8 +++ .../buildings-channel-condition-model.cc | 54 +++++++++++++++++++ .../model/three-gpp-propagation-loss-model.cc | 47 ++++++++++++++-- .../model/three-gpp-propagation-loss-model.h | 30 +++++++++++ 5 files changed, 137 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2f2b2e8e0..305c1cdc4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -65,6 +65,7 @@ Changes from ns-3.38 to ns-3-dev ### Changed behavior +* (buildings) Calculation of the O2I Low/High Building Penetration Losses based on 3GPP 38.901 7.4.3.1 was missing. These losses are now included in the pathloss calculation when buildings are present. * (network) The function `Buffer::Allocate` will over-provision `ALLOC_OVER_PROVISION` bytes when allocating buffers for packets. `ALLOC_OVER_PROVISION` is currently set to 100 bytes. Changes from ns-3.37 to ns-3.38 diff --git a/src/buildings/doc/source/buildings-user.rst b/src/buildings/doc/source/buildings-user.rst index 5ae47dbda..92b0e8f9f 100644 --- a/src/buildings/doc/source/buildings-user.rst +++ b/src/buildings/doc/source/buildings-user.rst @@ -194,6 +194,14 @@ Building-aware channel condition models The class BuildingsChannelConditionModel implements a `channel condition model `_ which determines the LOS/NLOS channel state based on the buildings deployed in the scenario. +In addition, based on the wall material of the building, low/high building +penetration losses are considered, as defined in 3GPP TS 38.901 7.4.3.1. +In particular, for O2I condition, in case of Wood or ConcreteWithWindows material, +low losses are considered in the pathloss calculation. In case the material has +been set to ConcreteWithoutWindows or StoneBlocks, high losses are considered. +Notice that in certain corner cases, such as the I2O2I interference, the model +underestimates losses by applying either low or high losses based on the wall material +of the involved nodes. For a more accurate estimation the model can be further extended. The classes ``ThreeGppV2vUrbanChannelConditionModel`` and ``ThreeGppV2vHighwayChannelConditionModel`` implement hybrid channel condition diff --git a/src/buildings/model/buildings-channel-condition-model.cc b/src/buildings/model/buildings-channel-condition-model.cc index 5e89c598b..8b1dfbcb1 100644 --- a/src/buildings/model/buildings-channel-condition-model.cc +++ b/src/buildings/model/buildings-channel-condition-model.cc @@ -99,6 +99,35 @@ BuildingsChannelConditionModel::GetChannelCondition(Ptr a, { NS_LOG_DEBUG("a and b are indoor in different buildings"); cond->SetLosCondition(ChannelCondition::LosConditionValue::NLOS); + + ChannelCondition::O2iLowHighConditionValue lowHighLossConditionA1; + ChannelCondition::O2iLowHighConditionValue lowHighLossConditionB1; + + // Low losses considered for Wood or ConcreteWithWindows, while + // high losses for ConcreteWithoutWindows and StoneBlocks + lowHighLossConditionA1 = + a1->GetBuilding()->GetExtWallsType() == Building::ExtWallsType_t::Wood || + a1->GetBuilding()->GetExtWallsType() == + Building::ExtWallsType_t::ConcreteWithWindows + ? ChannelCondition::O2iLowHighConditionValue::LOW + : ChannelCondition::O2iLowHighConditionValue::HIGH; + + lowHighLossConditionB1 = + b1->GetBuilding()->GetExtWallsType() == Building::ExtWallsType_t::Wood || + b1->GetBuilding()->GetExtWallsType() == + Building::ExtWallsType_t::ConcreteWithWindows + ? ChannelCondition::O2iLowHighConditionValue::LOW + : ChannelCondition::O2iLowHighConditionValue::HIGH; + + if (lowHighLossConditionA1 == ChannelCondition::O2iLowHighConditionValue::HIGH || + lowHighLossConditionB1 == ChannelCondition::O2iLowHighConditionValue::HIGH) + { + cond->SetO2iLowHighCondition(ChannelCondition::O2iLowHighConditionValue::HIGH); + } + else + { + cond->SetO2iLowHighCondition(ChannelCondition::O2iLowHighConditionValue::LOW); + } } } else // outdoor to indoor case @@ -107,6 +136,31 @@ BuildingsChannelConditionModel::GetChannelCondition(Ptr a, NS_LOG_DEBUG("a is indoor and b outdoor or vice-versa"); cond->SetLosCondition(ChannelCondition::LosConditionValue::NLOS); + + ChannelCondition::O2iLowHighConditionValue lowHighLossCondition; + if (isAIndoor) + { + // Low losses considered for Wood or ConcreteWithWindows, while + // high losses for ConcreteWithoutWindows and StoneBlocks + lowHighLossCondition = + a1->GetBuilding()->GetExtWallsType() == Building::ExtWallsType_t::Wood || + a1->GetBuilding()->GetExtWallsType() == + Building::ExtWallsType_t::ConcreteWithWindows + ? ChannelCondition::O2iLowHighConditionValue::LOW + : ChannelCondition::O2iLowHighConditionValue::HIGH; + + cond->SetO2iLowHighCondition(lowHighLossCondition); + } + else + { + lowHighLossCondition = + b1->GetBuilding()->GetExtWallsType() == Building::ExtWallsType_t::Wood || + b1->GetBuilding()->GetExtWallsType() == + Building::ExtWallsType_t::ConcreteWithWindows + ? ChannelCondition::O2iLowHighConditionValue::LOW + : ChannelCondition::O2iLowHighConditionValue::HIGH; + cond->SetO2iLowHighCondition(lowHighLossCondition); + } } return cond; diff --git a/src/propagation/model/three-gpp-propagation-loss-model.cc b/src/propagation/model/three-gpp-propagation-loss-model.cc index dcdab6494..7f2855a7e 100644 --- a/src/propagation/model/three-gpp-propagation-loss-model.cc +++ b/src/propagation/model/three-gpp-propagation-loss-model.cc @@ -144,6 +144,12 @@ ThreeGppPropagationLossModel::GetFrequency() const return m_frequency; } +bool +ThreeGppPropagationLossModel::IsO2iLowPenetrationLoss(Ptr cond) const +{ + return DoIsO2iLowPenetrationLoss(cond); +} + double ThreeGppPropagationLossModel::DoCalcRxPower(double txPowerDbm, Ptr a, @@ -179,17 +185,26 @@ ThreeGppPropagationLossModel::DoCalcRxPower(double txPowerDbm, if (cond->GetO2iCondition() == ChannelCondition::O2iConditionValue::O2I && m_buildingPenLossesEnabled) { - if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::LOW) + if (IsO2iLowPenetrationLoss(cond)) { rxPow -= GetO2iLowPenetrationLoss(a, b, cond->GetLosCondition()); } - else if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::HIGH) + else { rxPow -= GetO2iHighPenetrationLoss(a, b, cond->GetLosCondition()); } + } + else if (cond->GetO2iCondition() == ChannelCondition::O2iConditionValue::I2I && + cond->GetLosCondition() == ChannelCondition::LosConditionValue::NLOS && + m_buildingPenLossesEnabled) + { + if (IsO2iLowPenetrationLoss(cond)) + { + rxPow -= GetO2iLowPenetrationLoss(a, b, cond->GetLosCondition()); + } else { - NS_ABORT_MSG("If we have set the O2I condition, we shouldn't be here"); + rxPow -= GetO2iHighPenetrationLoss(a, b, cond->GetLosCondition()); } } @@ -368,6 +383,23 @@ ThreeGppPropagationLossModel::GetO2iHighPenetrationLoss( return o2iLossValue; } +bool +ThreeGppPropagationLossModel::DoIsO2iLowPenetrationLoss(Ptr cond) const +{ + if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::LOW) + { + return true; + } + else if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::HIGH) + { + return false; + } + else + { + NS_ABORT_MSG("If we have set the O2I condition, we shouldn't be here"); + } +} + double ThreeGppPropagationLossModel::GetLossNlosv(double distance2D, double distance3D, @@ -547,6 +579,15 @@ ThreeGppRmaPropagationLossModel::GetO2iDistance2dIn() const return std::min(m_randomO2iVar1->GetValue(0, 10), m_randomO2iVar2->GetValue(0, 10)); } +bool +ThreeGppRmaPropagationLossModel::DoIsO2iLowPenetrationLoss(Ptr cond + [[maybe_unused]]) const +{ + // Based on 3GPP 38.901 7.4.3.1 in RMa only low losses are applied. + // Therefore enforce low losses. + return true; +} + double ThreeGppRmaPropagationLossModel::GetLossLos(double distance2D, double distance3D, diff --git a/src/propagation/model/three-gpp-propagation-loss-model.h b/src/propagation/model/three-gpp-propagation-loss-model.h index be8617cd8..c664fafcc 100644 --- a/src/propagation/model/three-gpp-propagation-loss-model.h +++ b/src/propagation/model/three-gpp-propagation-loss-model.h @@ -78,6 +78,14 @@ class ThreeGppPropagationLossModel : public PropagationLossModel */ double GetFrequency() const; + /** + * \brief Return true if the O2I Building Penetration loss + * corresponds to a low loss condition. + * \param cond The ptr to the channel condition model + * \return True for low loss, false for high + */ + bool IsO2iLowPenetrationLoss(Ptr cond) const; + private: /** * Computes the received power by applying the pathloss model described in @@ -173,6 +181,20 @@ class ThreeGppPropagationLossModel : public PropagationLossModel Ptr b, ChannelCondition::LosConditionValue cond) const; + /** + * \brief Indicates the condition of the o2i building penetration loss + * (defined in 3GPP TR 38.901 7.4.3.1). + * The default implementation returns the condition as set + * (either based on the buildings materials, or if the probabilistic + * model is used in the ThreeGppChannelConditionModel, then + * based on the result of a random variable). + * The derived classes can change the default behavior by overriding + * this method. + * \param cond the ptr to the channel condition model + * \return True for low losses, false for high losses + */ + virtual bool DoIsO2iLowPenetrationLoss(Ptr cond) const; + /** * \brief Computes the pathloss between a and b considering that the line of * sight is obstructed @@ -374,6 +396,14 @@ class ThreeGppRmaPropagationLossModel : public ThreeGppPropagationLossModel */ double GetO2iDistance2dIn() const override; + /** + * \brief Indicates the condition of the o2i building penetration loss + * (defined in 3GPP TR 38.901 7.4.3.1). + * \param cond the ptr to the channel condition model + * \return True for low losses, false for high losses + */ + bool DoIsO2iLowPenetrationLoss(Ptr cond) const override; + /** * \brief Computes the pathloss between a and b considering that the line of * sight is obstructed