From a9daf34daade51495dc1b976185d968c6421ce13 Mon Sep 17 00:00:00 2001 From: Katerina Koutlia Date: Thu, 4 Nov 2021 17:26:12 +0100 Subject: [PATCH] channel-condition-model: Calculate new 02I losses only when channel condition changes --- .../model/three-gpp-propagation-loss-model.cc | 193 +++++++++++++----- .../model/three-gpp-propagation-loss-model.h | 37 +++- 2 files changed, 174 insertions(+), 56 deletions(-) diff --git a/src/propagation/model/three-gpp-propagation-loss-model.cc b/src/propagation/model/three-gpp-propagation-loss-model.cc index 1e000eb2a..f5954a9fa 100644 --- a/src/propagation/model/three-gpp-propagation-loss-model.cc +++ b/src/propagation/model/three-gpp-propagation-loss-model.cc @@ -62,6 +62,10 @@ ThreeGppPropagationLossModel::GetTypeId (void) BooleanValue (false), MakeBooleanAccessor (&ThreeGppPropagationLossModel::m_enforceRanges), MakeBooleanChecker ()) + .AddAttribute ("BuildingPenetrationLossesEnabled", "Enable/disable Building Penetration Losses.", + BooleanValue (true), + MakeBooleanAccessor (&ThreeGppPropagationLossModel::m_buildingPenLossesEnabled), + MakeBooleanChecker ()) ; return tid; } @@ -162,6 +166,23 @@ ThreeGppPropagationLossModel::DoCalcRxPower (double txPowerDbm, rxPow -= GetShadowing (a, b, cond->GetLosCondition ()); } + //get o2i losses + if (cond->GetO2iCondition () == ChannelCondition::O2iConditionValue::O2I && m_buildingPenLossesEnabled) + { + if (cond->GetO2iLowHighCondition () == ChannelCondition::O2iLowHighConditionValue::LOW) + { + rxPow -= GetO2iLowPenetrationLoss (a, b, cond->GetLosCondition ()); + } + else if (cond->GetO2iLowHighCondition () == ChannelCondition::O2iLowHighConditionValue::HIGH) + { + rxPow -= GetO2iHighPenetrationLoss (a, b, cond->GetLosCondition ()); + } + else + { + NS_ABORT_MSG ("If we have set the O2I condition, we shouldn't be here"); + } + } + return rxPow; } @@ -188,81 +209,145 @@ ThreeGppPropagationLossModel::GetLoss (Ptr cond, double distan NS_FATAL_ERROR ("Unknown channel condition"); } - if (cond->GetO2iCondition () == ChannelCondition::O2iConditionValue::O2I) - { - if (cond->GetO2iLowHighCondition () == ChannelCondition::O2iLowHighConditionValue::LOW) - { - loss += GetO2iLowPenetrationLoss (); - } - else if (cond->GetO2iLowHighCondition () == ChannelCondition::O2iLowHighConditionValue::HIGH) - { - loss += GetO2iHighPenetrationLoss (); - } - else - { - NS_ABORT_MSG ("If we have set the O2I condition, we shouldn't be here"); - } - } - return loss; } double -ThreeGppPropagationLossModel::GetO2iLowPenetrationLoss () const +ThreeGppPropagationLossModel::GetO2iLowPenetrationLoss (Ptr a, + Ptr b, + ChannelCondition::LosConditionValue cond) const { - double lowLossTw = 0; - double lossIn = 0; - double lowlossStdDeviation = 0; - double lGlass = 0; - double lConcrete = 0; + NS_LOG_FUNCTION (this); - // distance2dIn is minimum of two independently generated uniformly distributed - // variables between 0 and 25 m for UMa and UMi-Street Canyon, and between 0 and - // 10 m for RMa. 2D−in d shall be UT-specifically generated. - double distance2dIn = GetO2iDistance2dIn (); + double o2iLossValue = 0; + double lowLossTw = 0; + double lossIn = 0; + double lowlossNormalVariate = 0; + double lGlass = 0; + double lConcrete = 0; - // calculate material penetration losses, see Table 7.4.3-1 - lGlass = 2 + 0.2 * m_frequency/1e9; // m_frequency is operation frequency in Hz - lConcrete = 5 + 4 * m_frequency/1e9; + // compute the channel key + uint32_t key = GetKey (a, b); - lowLossTw = 5 - 10 * log10 (0.3 * std::pow (10, -lGlass/10) + 0.7 * std::pow (10, -lConcrete/10)); + bool notFound = false; // indicates if the o2iLoss value has not been computed yet + bool newCondition = false; // indicates if the channel condition has changed - // calculate indoor loss - lossIn = 0.5 * distance2dIn; + auto it = m_o2iLossMap.end (); // the o2iLoss map iterator + if (m_o2iLossMap.find (key) != m_o2iLossMap.end ()) + { + // found the o2iLoss value in the map + it = m_o2iLossMap.find (key); + newCondition = (it->second.m_condition != cond); // true if the condition changed + } + else + { + notFound = true; + // add a new entry in the map and update the iterator + O2iLossMapItem newItem; + it = m_o2iLossMap.insert (it, std::make_pair (key, newItem)); + } - // calculate low loss standard deviation - lowlossStdDeviation = m_normalO2iLowLossVar->GetValue (); + if (notFound || newCondition) + { + // distance2dIn is minimum of two independently generated uniformly distributed + // variables between 0 and 25 m for UMa and UMi-Street Canyon, and between 0 and + // 10 m for RMa. 2D−in d shall be UT-specifically generated. + double distance2dIn = GetO2iDistance2dIn (); - return lowLossTw + lossIn + lowlossStdDeviation; + // calculate material penetration losses, see Table 7.4.3-1 + lGlass = 2 + 0.2 * m_frequency/1e9; // m_frequency is operation frequency in Hz + lConcrete = 5 + 4 * m_frequency/1e9; + + lowLossTw = 5 - 10 * log10 (0.3 * std::pow (10, -lGlass/10) + 0.7 * std::pow (10, -lConcrete/10)); + + // calculate indoor loss + lossIn = 0.5 * distance2dIn; + + // calculate low loss standard deviation + lowlossNormalVariate = m_normalO2iLowLossVar->GetValue (); + + o2iLossValue = lowLossTw + lossIn + lowlossNormalVariate; + } + else + { + o2iLossValue = it->second.m_o2iLoss; + } + + // update the entry in the map + it->second.m_o2iLoss = o2iLossValue; + it->second.m_condition = cond; + + return o2iLossValue; } double -ThreeGppPropagationLossModel::GetO2iHighPenetrationLoss () const +ThreeGppPropagationLossModel::GetO2iHighPenetrationLoss (Ptr a, + Ptr b, + ChannelCondition::LosConditionValue cond) const { - double highLossTw = 0; - double lossIn = 0; - double highlossStdDeviation = 0; - double lIIRGlass = 0; - double lConcrete = 0; + NS_LOG_FUNCTION (this); - // distance2dIn is minimum of two independently generated uniformly distributed - // variables between 0 and 25 m for UMa and UMi-Street Canyon, and between 0 and - // 10 m for RMa. 2D−in d shall be UT-specifically generated. - double distance2dIn = GetO2iDistance2dIn (); + double o2iLossValue = 0; + double highLossTw = 0; + double lossIn = 0; + double highlossNormalVariate = 0; + double lIIRGlass = 0; + double lConcrete = 0; - // calculate material penetration losses, see Table 7.4.3-1 - lIIRGlass = 23 + 0.3 * m_frequency/1e9; - lConcrete = 5 + 4 * m_frequency/1e9; + // compute the channel key + uint32_t key = GetKey (a, b); - highLossTw = 5 - 10 * log10 (0.7 * std::pow (10, -lIIRGlass/10) + 0.3 * std::pow (10, -lConcrete/10)); + bool notFound = false; // indicates if the o2iLoss value has not been computed yet + bool newCondition = false; // indicates if the channel condition has changed - // calculate indoor loss - lossIn = 0.5 * distance2dIn; + auto it = m_o2iLossMap.end (); // the o2iLoss map iterator + if (m_o2iLossMap.find (key) != m_o2iLossMap.end ()) + { + // found the o2iLoss value in the map + it = m_o2iLossMap.find (key); + newCondition = (it->second.m_condition != cond); // true if the condition changed + } + else + { + notFound = true; + // add a new entry in the map and update the iterator + O2iLossMapItem newItem; + it = m_o2iLossMap.insert (it, std::make_pair (key, newItem)); + } - // calculate low loss standard deviation - highlossStdDeviation = m_normalO2iHighLossVar->GetValue (); + if (notFound || newCondition) + { + // generate a new independent realization - return highLossTw + lossIn + highlossStdDeviation; + // distance2dIn is minimum of two independently generated uniformly distributed + // variables between 0 and 25 m for UMa and UMi-Street Canyon, and between 0 and + // 10 m for RMa. 2D−in d shall be UT-specifically generated. + double distance2dIn = GetO2iDistance2dIn (); + + // calculate material penetration losses, see Table 7.4.3-1 + lIIRGlass = 23 + 0.3 * m_frequency/1e9; + lConcrete = 5 + 4 * m_frequency/1e9; + + highLossTw = 5 - 10 * log10 (0.7 * std::pow (10, -lIIRGlass/10) + 0.3 * std::pow (10, -lConcrete/10)); + + // calculate indoor loss + lossIn = 0.5 * distance2dIn; + + // calculate low loss standard deviation + highlossNormalVariate = m_normalO2iHighLossVar->GetValue (); + + o2iLossValue = highLossTw + lossIn + highlossNormalVariate; + } + else + { + o2iLossValue = it->second.m_o2iLoss; + } + + // update the entry in the map + it->second.m_o2iLoss = o2iLossValue; + it->second.m_condition = cond; + + return o2iLossValue; } double diff --git a/src/propagation/model/three-gpp-propagation-loss-model.h b/src/propagation/model/three-gpp-propagation-loss-model.h index 1cf0a117a..a2b2b72c9 100644 --- a/src/propagation/model/three-gpp-propagation-loss-model.h +++ b/src/propagation/model/three-gpp-propagation-loss-model.h @@ -120,9 +120,31 @@ private: virtual double GetO2iDistance2dIn () const = 0; // TODO all child classes should implement this function and this function should be purely virtual - virtual double GetO2iLowPenetrationLoss () const; + /** + * \brief Retrieves the o2i Loss value by looking at m_o2iLossMap. + * If not found or if the channel condition changed it generates a new + * independent realization and stores it in the map, otherwise it calculates + * a new value as defined in 3GPP TR38.901 7.4.3. + * \param a tx mobility model (used for the key calculation) + * \param b rx mobility model (used for the key calculation) + * \param cond the LOS/NLOS channel condition + * \return o2iLoss + */ + virtual double GetO2iLowPenetrationLoss (Ptr a, Ptr b, + ChannelCondition::LosConditionValue cond) const; - virtual double GetO2iHighPenetrationLoss () const; + /** + * \brief Retrieves the o2i Loss value by looking at m_o2iLossMap. + * If not found or if the channel condition changed it generates a new + * independent realization and stores it in the map, otherwise it calculates + * a new value as defined in 3GPP TR38.901 7.4.3. + * \param a tx mobility model (used for the key calculation) + * \param b rx mobility model (used for the key calculation) + * \param cond the LOS/NLOS channel condition + * \return o2iLoss + */ + virtual double GetO2iHighPenetrationLoss (Ptr a, Ptr b, + ChannelCondition::LosConditionValue cond) const; /** * \brief Computes the pathloss between a and b considering that the line of @@ -226,6 +248,7 @@ protected: double m_frequency; //!< operating frequency in Hz bool m_shadowingEnabled; //!< enable/disable shadowing bool m_enforceRanges; //!< strictly enforce TR 38.901 parameter ranges + bool m_buildingPenLossesEnabled; //!< enable/disable building penetration losses Ptr m_normRandomVariable; //!< normal random variable /** Define a struct for the m_shadowingMap entries */ @@ -238,6 +261,16 @@ protected: mutable std::unordered_map m_shadowingMap; //!< map to store the shadowing values + /** Define a struct for the m_o2iLossMap entries */ + struct O2iLossMapItem + { + double m_o2iLoss; //!< the o2i loss in dB + ChannelCondition::LosConditionValue m_condition; //!< the LOS/NLOS condition + }; + + mutable std::unordered_map m_o2iLossMap; //!< map to store the o2i Loss values + + Ptr m_randomO2iVar1; //!< a uniform random variable for the calculation of the indoor loss, see TR38.901 Table 7.4.3-2 Ptr m_randomO2iVar2; //!< a uniform random variable for the calculation of the indoor loss, see TR38.901 Table 7.4.3-2 Ptr m_normalO2iLowLossVar; //!< a normal random variable for the calculation of 02i low loss, see TR38.901 Table 7.4.3-2