diff --git a/src/wifi/model/interference-helper.cc b/src/wifi/model/interference-helper.cc --- a/src/wifi/model/interference-helper.cc +++ b/src/wifi/model/interference-helper.cc @@ -25,6 +25,8 @@ #include "ns3/log.h" #include +using TimeInterval = boost::icl::interval; + namespace ns3 { NS_LOG_COMPONENT_DEFINE ("InterferenceHelper"); @@ -84,47 +86,14 @@ /**************************************************************** - * Class which records SNIR change events for a - * short period of time. - ****************************************************************/ - -InterferenceHelper::NiChange::NiChange (double power, Ptr event) - : m_power (power), - m_event (event) -{ -} - -double -InterferenceHelper::NiChange::GetPower (void) const -{ - return m_power; -} - -void -InterferenceHelper::NiChange::AddPower (double power) -{ - m_power += power; -} - -Ptr -InterferenceHelper::NiChange::GetEvent (void) const -{ - return m_event; -} - - -/**************************************************************** * The actual InterferenceHelper ****************************************************************/ InterferenceHelper::InterferenceHelper () : m_errorRateModel (0), m_numRxAntennas (1), - m_firstPower (0), m_rxing (false) { - // Always have a zero power noise event in the list - AddNiChangeEvent (Time (0), NiChange (0.0, 0)); } InterferenceHelper::~InterferenceHelper () @@ -184,43 +153,44 @@ Time InterferenceHelper::GetEnergyDuration (double energyW) const { - Time now = Simulator::Now (); - auto i = GetPreviousPosition (now); - Time end = i->first; - for (; i != m_niChanges.end (); ++i) + const Time now = Simulator::Now (); + + Time last = Time::Min(); + + for (auto i = m_niChanges.find(now), end = m_niChanges.end (); i != end; ++i) { - double noiseInterferenceW = i->second.GetPower (); - end = i->first; + double noiseInterferenceW = i->second; + last = i->first.upper(); if (noiseInterferenceW < energyW) { break; } } - return end > now ? end - now : MicroSeconds (0); + return last > now ? last - now : MicroSeconds (0); } void InterferenceHelper::AppendEvent (Ptr event) { NS_LOG_FUNCTION (this); - double previousPowerStart = 0; - double previousPowerEnd = 0; - previousPowerStart = GetPreviousPosition (event->GetStartTime ())->second.GetPower (); - previousPowerEnd = GetPreviousPosition (event->GetEndTime ())->second.GetPower (); if (!m_rxing) { - m_firstPower = previousPowerStart; - // Always leave the first zero power noise event in the list - m_niChanges.erase (++(m_niChanges.begin ()), - GetNextPosition (event->GetStartTime ())); + // Remove all events before this event, do not include the start time + m_niChanges -= TimeInterval::right_open(Seconds(0), event->GetStartTime ()); } - auto first = AddNiChangeEvent (event->GetStartTime (), NiChange (previousPowerStart, event)); - auto last = AddNiChangeEvent (event->GetEndTime (), NiChange (previousPowerEnd, event)); - for (auto i = first; i != last; ++i) - { - i->second.AddPower (event->GetRxPowerW ()); - } + + auto inter = TimeInterval::closed(event->GetStartTime (), event->GetEndTime ()); + + m_niChanges += std::make_pair(inter, event->GetRxPowerW()); + + /*std::cout << inter << " " << event->GetRxPowerW() << std::endl; + //std::cout << m_niChanges.size() << std::endl; + for (auto i = m_niChanges.begin(), end = m_niChanges.end(); i != end; ++i) + { + std::cout << i->first << " " << i->second << std::endl; + } + std::cout << std::endl;*/ } double @@ -239,10 +209,12 @@ } double -InterferenceHelper::CalculateNoiseInterferenceW (Ptr event, NiChanges *ni) const +InterferenceHelper::CalculateNoiseInterferenceW (Ptr event, NiChangesRange *ni) const { - double noiseInterference = m_firstPower; - auto it = m_niChanges.find (event->GetStartTime ()); + // Get all the powers between this event's start and end time inclusive + *ni = m_niChanges.equal_range(TimeInterval::closed(event->GetStartTime (), event->GetEndTime())); + + /*auto it = m_niChanges.find (event->GetStartTime ()); for (; it != m_niChanges.end () && it->second.GetEvent () != event; ++it) { noiseInterference = it->second.GetPower (); @@ -252,8 +224,10 @@ { ni->insert (*it); } - ni->emplace (event->GetEndTime (), NiChange (0, event)); - return noiseInterference; + ni->emplace (event->GetEndTime (), NiChange (0, event));*/ + + // If there are no events, then there is no interference + return ni->first == ni->second ? 0 : ni->first->second - event->GetRxPowerW (); } double @@ -279,61 +253,64 @@ } double -InterferenceHelper::CalculatePlcpPayloadPer (Ptr event, NiChanges *ni) const +InterferenceHelper::CalculatePlcpPayloadPer (Ptr event, const NiChangesRange& ni) const { NS_LOG_FUNCTION (this); const WifiTxVector txVector = event->GetTxVector (); + const double powerW = event->GetRxPowerW (); + double psr = 1.0; /* Packet Success Rate */ - auto j = ni->begin (); - Time previous = j->first; + WifiMode payloadMode = event->GetPayloadMode (); WifiPreamble preamble = txVector.GetPreambleType (); - Time plcpHeaderStart = j->first + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble + Time plcpHeaderStart = event->GetStartTime() + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (txVector); //packet start time + preamble + L-SIG Time plcpTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble) + WifiPhy::GetPlcpSigA1Duration (preamble) + WifiPhy::GetPlcpSigA2Duration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A Time plcpPayloadStart = plcpTrainingSymbolsStart + WifiPhy::GetPlcpTrainingSymbolDuration (txVector) + WifiPhy::GetPlcpSigBDuration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B - double noiseInterferenceW = m_firstPower; - double powerW = event->GetRxPowerW (); - while (++j != ni->end ()) + + for (auto j = ni.first, end = ni.second; j != end; ++j) { - Time current = j->first; - NS_LOG_DEBUG ("previous= " << previous << ", current=" << current); - NS_ASSERT (current >= previous); - //Case 1: Both previous and current point to the payload - if (previous >= plcpPayloadStart) + const Time startt = j->first.lower(); + const Time endt = j->first.upper(); + + const double noiseInterferenceW = j->second - powerW; + + NS_LOG_DEBUG ("startt= " << startt << ", endt=" << endt << ", noiseInterferenceW=" << noiseInterferenceW); + + //Case 1: This interval is after the payload has started + if (startt >= plcpPayloadStart) { psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, noiseInterferenceW, txVector.GetChannelWidth ()), - current - previous, + endt - startt, payloadMode, txVector); NS_LOG_DEBUG ("Both previous and current point to the payload: mode=" << payloadMode << ", psr=" << psr); } - //Case 2: previous is before payload and current is in the payload - else if (current >= plcpPayloadStart) + //Case 2: This interval starts before the payload, but it does include it + else if (startt < plcpPayloadStart && plcpPayloadStart <= endt) { psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, noiseInterferenceW, txVector.GetChannelWidth ()), - current - plcpPayloadStart, + endt - plcpPayloadStart, payloadMode, txVector); NS_LOG_DEBUG ("previous is before payload and current is in the payload: mode=" << payloadMode << ", psr=" << psr); } - noiseInterferenceW = j->second.GetPower () - powerW; - previous = j->first; } double per = 1 - psr; return per; } double -InterferenceHelper::CalculatePlcpHeaderPer (Ptr event, NiChanges *ni) const +InterferenceHelper::CalculatePlcpHeaderPer (Ptr event, const NiChangesRange& ni) const { NS_LOG_FUNCTION (this); const WifiTxVector txVector = event->GetTxVector (); + const double powerW = event->GetRxPowerW (); + double psr = 1.0; /* Packet Success Rate */ - auto j = ni->begin (); - Time previous = j->first; + WifiPreamble preamble = txVector.GetPreambleType (); WifiMode mcsHeaderMode; if (preamble == WIFI_PREAMBLE_HT_MF || preamble == WIFI_PREAMBLE_HT_GF) @@ -352,22 +329,25 @@ mcsHeaderMode = WifiPhy::GetHePlcpHeaderMode (); } WifiMode headerMode = WifiPhy::GetPlcpHeaderMode (txVector); - Time plcpHeaderStart = j->first + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble + Time plcpHeaderStart = event->GetStartTime() + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (txVector); //packet start time + preamble + L-SIG Time plcpTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble) + WifiPhy::GetPlcpSigA1Duration (preamble) + WifiPhy::GetPlcpSigA2Duration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A Time plcpPayloadStart = plcpTrainingSymbolsStart + WifiPhy::GetPlcpTrainingSymbolDuration (txVector) + WifiPhy::GetPlcpSigBDuration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B - double noiseInterferenceW = m_firstPower; - double powerW = event->GetRxPowerW (); - while (++j != ni->end ()) + + for (auto j = ni.first, end = ni.second; j != end; ++j) { - Time current = j->first; - NS_LOG_DEBUG ("previous= " << previous << ", current=" << current); - NS_ASSERT (current >= previous); - //Case 1: previous and current after playload start: nothing to do - if (previous >= plcpPayloadStart) + const Time startt = j->first.lower(); + const Time endt = j->first.upper(); + + const double noiseInterferenceW = j->second - powerW; + + NS_LOG_DEBUG ("startt= " << startt << ", endt=" << endt << ", noiseInterferenceW=" << noiseInterferenceW); + + //Case 1: interval after playload start: nothing to do + if (startt >= plcpPayloadStart && endt >= plcpPayloadStart) { - psr *= 1; - NS_LOG_DEBUG ("Case 1 - previous and current after playload start: nothing to do"); + //psr *= 1; + NS_LOG_DEBUG ("Case 1 - interval after playload start: nothing to do"); } //Case 2: previous is in training or in SIG-B: legacy will not enter here since it didn't enter in the last two and they are all the same for legacy else if (previous >= plcpTrainingSymbolsStart) @@ -732,9 +712,6 @@ NS_LOG_DEBUG ("Case 5d - previous is in the preamble and current is in L-SIG: mode=" << headerMode << ", psr=" << psr); } } - - noiseInterferenceW = j->second.GetPower () - powerW; - previous = j->first; } double per = 1 - psr; @@ -744,7 +721,7 @@ struct InterferenceHelper::SnrPer InterferenceHelper::CalculatePlcpPayloadSnrPer (Ptr event) const { - NiChanges ni; + NiChangesRange ni; double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni); double snr = CalculateSnr (event->GetRxPowerW (), noiseInterferenceW, @@ -753,7 +730,7 @@ /* calculate the SNIR at the start of the packet and accumulate * all SNIR changes in the snir vector. */ - double per = CalculatePlcpPayloadPer (event, &ni); + double per = CalculatePlcpPayloadPer (event, ni); struct SnrPer snrPer; snrPer.snr = snr; @@ -764,7 +741,7 @@ struct InterferenceHelper::SnrPer InterferenceHelper::CalculatePlcpHeaderSnrPer (Ptr event) const { - NiChanges ni; + NiChangesRange ni; double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni); double snr = CalculateSnr (event->GetRxPowerW (), noiseInterferenceW, @@ -773,7 +750,7 @@ /* calculate the SNIR at the start of the plcp header and accumulate * all SNIR changes in the snir vector. */ - double per = CalculatePlcpHeaderPer (event, &ni); + double per = CalculatePlcpHeaderPer (event, ni); struct SnrPer snrPer; snrPer.snr = snr; @@ -785,32 +762,7 @@ InterferenceHelper::EraseEvents (void) { m_niChanges.clear (); - // Always have a zero power noise event in the list - AddNiChangeEvent (Time (0), NiChange (0.0, 0)); m_rxing = false; - m_firstPower = 0; -} - -InterferenceHelper::NiChanges::const_iterator -InterferenceHelper::GetNextPosition (Time moment) const -{ - return m_niChanges.upper_bound (moment); -} - -InterferenceHelper::NiChanges::const_iterator -InterferenceHelper::GetPreviousPosition (Time moment) const -{ - auto it = GetNextPosition (moment); - // This is safe since there is always an NiChange at time 0, - // before moment. - --it; - return it; -} - -InterferenceHelper::NiChanges::iterator -InterferenceHelper::AddNiChangeEvent (Time moment, NiChange change) -{ - return m_niChanges.insert (GetNextPosition (moment), std::make_pair (moment, change)); } void @@ -825,10 +777,6 @@ { NS_LOG_FUNCTION (this); m_rxing = false; - //Update m_firstPower for frame capture - auto it = m_niChanges.find (Simulator::Now ()); - it--; - m_firstPower = it->second.GetPower (); } } //namespace ns3 diff --git a/src/wifi/model/interference-helper.h b/src/wifi/model/interference-helper.h --- a/src/wifi/model/interference-helper.h +++ b/src/wifi/model/interference-helper.h @@ -27,6 +27,8 @@ #include "error-rate-model.h" #include +#include + namespace ns3 { /** @@ -204,48 +206,11 @@ private: - /** - * Noise and Interference (thus Ni) event. - */ - class NiChange - { -public: - /** - * Create a NiChange at the given time and the amount of NI change. - * - * \param power the power - * \param event causes this NI change - */ - NiChange (double power, Ptr event); - /** - * Return the power - * - * \return the power - */ - double GetPower (void) const; - /** - * Add a given amount of power. - * - * \param power the power to be added to the existing value - */ - void AddPower (double power); - /** - * Return the event causes the corresponding NI change - * - * \return the event - */ - Ptr GetEvent (void) const; - - -private: - double m_power; ///< power - Ptr m_event; ///< event - }; - + typedef boost::icl::interval_map NiChanges; /** * typedef for a multimap of NiChanges */ - typedef std::multimap NiChanges; + typedef std::pair NiChangesRange; /** * Append the given Event. @@ -261,7 +226,7 @@ * * \return noise and interference power */ - double CalculateNoiseInterferenceW (Ptr event, NiChanges *ni) const; + double CalculateNoiseInterferenceW (Ptr event, NiChangesRange *ni) const; /** * Calculate SNR (linear ratio) from the given signal power and noise+interference power. * (Mode is not currently used) @@ -294,7 +259,7 @@ * * \return the error rate of the packet */ - double CalculatePlcpPayloadPer (Ptr event, NiChanges *ni) const; + double CalculatePlcpPayloadPer (Ptr event, const NiChangesRange& ni) const; /** * Calculate the error rate of the plcp header. The plcp header can be divided into * multiple chunks (e.g. due to interference from other transmissions). @@ -304,47 +269,15 @@ * * \return the error rate of the packet */ - double CalculatePlcpHeaderPer (Ptr event, NiChanges *ni) const; + double CalculatePlcpHeaderPer (Ptr event, const NiChangesRange& ni) const; double m_noiseFigure; /**< noise figure (linear) */ Ptr m_errorRateModel; ///< error rate model uint8_t m_numRxAntennas; /**< the number of RX antennas in the corresponding receiver */ /// Experimental: needed for energy duration calculation - NiChanges m_niChanges; - double m_firstPower; ///< first power + NiChanges m_niChanges; // partial_enricher allows storing intervals with 0 power bool m_rxing; ///< flag whether it is in receiving state - /** - * Returns an iterator to the first nichange that is later than moment - * - * \param moment time to check from - * \returns an iterator to the list of NiChanges - */ - NiChanges::const_iterator GetNextPosition (Time moment) const; - /** - * Returns an iterator to the first nichange that is later than moment - * - * \param moment time to check from - * \returns an iterator to the list of NiChanges - */ - //NiChanges::iterator GetNextPosition (Time moment); - /** - * Returns an iterator to the last nichange that is before than moment - * - * \param moment time to check from - * \returns an iterator to the list of NiChanges - */ - NiChanges::const_iterator GetPreviousPosition (Time moment) const; - - /** - * Add NiChange to the list at the appropriate position and - * return the iterator of the new event. - * - * \param moment - * \param change - * \returns the iterator of the new event - */ - NiChanges::iterator AddNiChangeEvent (Time moment, NiChange change); }; } //namespace ns3