29#include "ns3/he-ppdu.h" 
   31#include "ns3/packet.h" 
   32#include "ns3/simulator.h" 
   51      m_endTime(m_startTime + duration),
 
   52      m_rxPowerW(
std::move(rxPower))
 
   94                         [](
const auto& p1, 
const auto& p2) { return p1.second < p2.second; });
 
  119        auto band = currentRxPowerW.first;
 
  120        auto it = rxPower.find(band);
 
  121        if (it != rxPower.end())
 
  123            currentRxPowerW.second += it->second;
 
  137    os << 
"start=" << 
event.GetStartTime() << 
", end=" << 
event.GetEndTime()
 
  138       << 
", power=" << 
event.GetRxPowerW() << 
"W" 
  139       << 
", PPDU=" << 
event.GetPpdu();
 
  199                            .SetGroupName(
"Wifi")
 
  221                        bool isStartHePortionRxing)
 
  223    Ptr<Event> event = Create<Event>(ppdu, duration, std::move(rxPowerW));
 
  236    Ptr<WifiPpdu> fakePpdu = Create<WifiPpdu>(Create<WifiPsdu>(Create<Packet>(0), hdr),
 
  239    Add(fakePpdu, duration, rxPowerW);
 
  261    auto result = 
m_niChanges.insert({band, niChanges});
 
  280        const auto frequencies = it->first.frequencies;
 
  282            std::find_if(bands.cbegin(), bands.cend(), [frequencies](
const auto& item) {
 
  283                return frequencies == item.frequencies;
 
  284            }) != std::end(bands);
 
  297    for (
const auto& band : bands)
 
  340    for (; i != niIt->second.end(); ++i)
 
  342        double noiseInterferenceW = i->second.GetPower();
 
  344        if (noiseInterferenceW < energyW)
 
  356    for (
const auto& [band, power] : event->GetRxPowerWPerBand())
 
  360        double previousPowerStart = 0;
 
  361        double previousPowerEnd = 0;
 
  363        previousPowerStart = previousPowerPosition->second.GetPower();
 
  369            niIt->second.erase(++(niIt->second.begin()), ++previousPowerPosition);
 
  371        else if (isStartHePortionRxing)
 
  381        for (
auto i = 
first; i != last; ++i)
 
  383            i->second.AddPower(power);
 
  393    for (
const auto& [band, power] : rxPower)
 
  399        for (
auto i = 
first; i != last; ++i)
 
  401            i->second.AddPower(power);
 
  404    event->UpdateRxPowerW(rxPower);
 
  409                                 double noiseInterference,
 
  410                                 uint16_t channelWidth,
 
  413    NS_LOG_FUNCTION(
this << signal << noiseInterference << channelWidth << +nss);
 
  415    static const double BOLTZMANN = 1.3803e-23;
 
  417    double Nt = BOLTZMANN * 290 * channelWidth * 1e6;
 
  420    double noise = noiseFloor + noiseInterference;
 
  421    double snr = signal / noise; 
 
  422    NS_LOG_DEBUG(
"bandwidth(MHz)=" << channelWidth << 
", signal(W)= " << signal << 
", noise(W)=" 
  423                                   << noiseFloor << 
", interference(W)=" << noiseInterference
 
  433        NS_LOG_DEBUG(
"SNR improvement thanks to diversity: " << 10 * std::log10(gain) << 
"dB");
 
  447    double noiseInterferenceW = firstPower_it->second;
 
  450    auto it = niIt->second.find(event->GetStartTime());
 
  454    for (; it != niIt->second.end() && it->first < 
Simulator::Now(); ++it)
 
  457            (
event != it->second.GetEvent()))
 
  463        noiseInterferenceW = it->second.GetPower() - 
event->GetRxPowerW(band) - muMimoPowerW;
 
  464        if (std::abs(noiseInterferenceW) < std::numeric_limits<double>::epsilon())
 
  467            noiseInterferenceW = 0.0;
 
  470    it = niIt->second.find(event->GetStartTime());
 
  472    for (; it != niIt->second.end() && it->second.GetEvent() != event; ++it)
 
  477    ni.emplace(event->GetStartTime(), 
NiChange(0, event));
 
  478    while (++it != niIt->second.end() && it->second.GetEvent() != event)
 
  482    ni.emplace(event->GetEndTime(), 
NiChange(0, event));
 
  483    nis.insert({band, ni});
 
  485                  "CalculateNoiseInterferenceW returns negative value " << noiseInterferenceW);
 
  486    return noiseInterferenceW;
 
  495    auto it = niIt->second.begin();
 
  497    double muMimoPowerW = 0.0;
 
  498    for (; it != niIt->second.end() && it->first < 
Simulator::Now(); ++it)
 
  502            auto hePpdu = DynamicCast<HePpdu>(it->second.GetEvent()->GetPpdu()->Copy());
 
  508                    event->GetPpdu()->GetTxVector().GetHeMuUserInfoMap().cbegin()->first;
 
  509                const auto otherStaId = it->second.GetEvent()
 
  512                                            .GetHeMuUserInfoMap()
 
  515                if (staId == otherStaId)
 
  519                muMimoPowerW += it->second.GetEvent()->GetRxPowerW(band);
 
  538    auto nbits = 
static_cast<uint64_t
>(rate * duration.
GetSeconds());
 
  548                                                     uint16_t staId)
 const 
  556    auto nbits = 
static_cast<uint64_t
>(rate * duration.
GetSeconds());
 
  557    nbits /= txVector.
GetNss(staId); 
 
  571                                        uint16_t channelWidth,
 
  575                                        std::pair<Time, Time> window)
 const 
  577    NS_LOG_FUNCTION(
this << channelWidth << band << staId << window.first << window.second);
 
  579    const auto& niIt = nis->find(band)->second;
 
  580    auto j = niIt.cbegin();
 
  581    Time previous = j->first;
 
  582    double muMimoPowerW = 0.0;
 
  583    WifiMode payloadMode = 
event->GetPpdu()->GetTxVector().GetMode(staId);
 
  584    Time phyPayloadStart = j->first;
 
  586        event->GetPpdu()->GetType() !=
 
  590                                         event->GetPpdu()->GetTxVector());
 
  596    Time windowStart = phyPayloadStart + window.first;
 
  597    Time windowEnd = phyPayloadStart + window.second;
 
  600    double powerW = 
event->GetRxPowerW(band);
 
  601    while (++j != niIt.cend())
 
  603        Time current = j->first;
 
  604        NS_LOG_DEBUG(
"previous= " << previous << 
", current=" << current);
 
  609                                  event->GetPpdu()->GetTxVector().GetNss(staId));
 
  611        if (previous >= windowStart)
 
  614                                                    Min(windowEnd, current) - previous,
 
  615                                                    event->GetPpdu()->GetTxVector(),
 
  617            NS_LOG_DEBUG(
"Both previous and current point to the windowed payload: mode=" 
  618                         << payloadMode << 
", psr=" << psr);
 
  621        else if (current >= windowStart)
 
  624                                                    Min(windowEnd, current) - windowStart,
 
  625                                                    event->GetPpdu()->GetTxVector(),
 
  628                "previous is before windowed payload and current is in the windowed payload: mode=" 
  629                << payloadMode << 
", psr=" << psr);
 
  631        noiseInterferenceW = j->second.GetPower() - powerW;
 
  634            muMimoPowerW += j->second.GetEvent()->GetRxPowerW(band);
 
  636                "PPDU belongs to same MU-MIMO transmission: muMimoPowerW=" << muMimoPowerW);
 
  638        noiseInterferenceW -= muMimoPowerW;
 
  640        if (previous > windowEnd)
 
  643                                               << 
" after time window end=" << windowEnd);
 
  647    double per = 1 - psr;
 
  655    uint16_t channelWidth,
 
  661    auto niIt = nis->find(band)->second;
 
  662    auto j = niIt.begin();
 
  666    for (
const auto& section : phyHeaderSections)
 
  668        stopLastSection = 
Max(stopLastSection, section.second.first.second);
 
  671    Time previous = j->first;
 
  674    double powerW = 
event->GetRxPowerW(band);
 
  675    while (++j != niIt.end())
 
  677        Time current = j->first;
 
  678        NS_LOG_DEBUG(
"previous= " << previous << 
", current=" << current);
 
  680        double snr = 
CalculateSnr(powerW, noiseInterferenceW, channelWidth, 1);
 
  681        for (
const auto& section : phyHeaderSections)
 
  683            Time start = section.second.first.first;
 
  684            Time stop = section.second.first.second;
 
  686            if (previous <= stop || current >= start)
 
  688                Time duration = 
Min(stop, current) - 
Max(start, previous);
 
  693                                                     section.second.second,
 
  694                                                     event->GetPpdu()->GetTxVector(),
 
  697                                 << section.first << 
" [" << start << 
", " << stop << 
"] for " 
  698                                 << duration.
As(
Time::NS) << 
": mode=" << section.second.second
 
  703        noiseInterferenceW = j->second.GetPower() - powerW;
 
  705        if (previous > stopLastSection)
 
  707            NS_LOG_DEBUG(
"Stop: new previous=" << previous << 
" after stop of last section=" 
  718                                          uint16_t channelWidth,
 
  723    auto niIt = nis->find(band)->second;
 
  728    for (
const auto& section :
 
  729         phyEntity->GetPhyHeaderSections(event->GetPpdu()->GetTxVector(), niIt.begin()->first))
 
  731        if (section.first == header)
 
  733            sections[header] = section.second;
 
  738    if (!sections.empty())
 
  747                                           uint16_t channelWidth,
 
  750                                           std::pair<Time, Time> relativeMpduStartStop)
 const 
  752    NS_LOG_FUNCTION(
this << channelWidth << band << staId << relativeMpduStartStop.first
 
  753                         << relativeMpduStartStop.second);
 
  759                              event->GetPpdu()->GetTxVector().GetNss(staId));
 
  764    double per = 
CalculatePayloadPer(event, channelWidth, &ni, band, staId, relativeMpduStartStop);
 
  771                                 uint16_t channelWidth,
 
  777    double snr = 
CalculateSnr(event->GetRxPowerW(band), noiseInterferenceW, channelWidth, nss);
 
  783                                             uint16_t channelWidth,
 
  790    double snr = 
CalculateSnr(event->GetRxPowerW(band), noiseInterferenceW, channelWidth, 1);
 
  800InterferenceHelper::NiChanges::iterator
 
  803    return niIt->second.upper_bound(moment);
 
  806InterferenceHelper::NiChanges::iterator
 
  816InterferenceHelper::NiChanges::iterator
 
  819    return niIt->second.insert(
GetNextPosition(moment, niIt), std::make_pair(moment, change));
 
  844        m_firstPowers.find(niIt->first)->second = it->second.GetPower();
 
  862        (currentEvent->GetPpdu()->GetUid() == otherEvent->GetPpdu()->GetUid()))
 
  864        const auto currentTxVector = currentEvent->GetPpdu()->GetTxVector();
 
  865        const auto otherTxVector = otherEvent->GetPpdu()->GetTxVector();
 
  866        NS_ASSERT(currentTxVector.GetHeMuUserInfoMap().size() == 1);
 
  867        NS_ASSERT(otherTxVector.GetHeMuUserInfoMap().size() == 1);
 
  868        const auto currentUserInfo = currentTxVector.GetHeMuUserInfoMap().cbegin();
 
  869        const auto otherUserInfo = otherTxVector.GetHeMuUserInfoMap().cbegin();
 
  870        return (currentUserInfo->second.ru == otherUserInfo->second.ru);
 
handles interference calculations
Time m_startTime
start time
Event(Ptr< const WifiPpdu > ppdu, Time duration, RxPowerWattPerChannelBand &&rxPower)
Create an Event with the given parameters.
Ptr< const WifiPpdu > GetPpdu() const
Return the PPDU.
Ptr< const WifiPpdu > m_ppdu
PPDU.
void UpdateRxPowerW(const RxPowerWattPerChannelBand &rxPower)
Update the received power (W) for all bands, i.e.
Time GetEndTime() const
Return the end time of the signal.
Time GetDuration() const
Return the duration of the signal.
double GetRxPowerW() const
Return the total received power (W).
RxPowerWattPerChannelBand m_rxPowerW
received power in watts per band
const RxPowerWattPerChannelBand & GetRxPowerWPerBand() const
Return the received power (W) for all bands.
Time GetStartTime() const
Return the start time of the signal.
void UpdatePpdu(Ptr< const WifiPpdu > ppdu)
Update the PPDU that initially generated the event.
TxPsdFlag
The transmit power spectral density flag, namely used to correctly build PSDs for pre-HE and HE porti...
@ PSD_HE_PORTION
HE portion of an HE PPDU.
Noise and Interference (thus Ni) event.
void AddPower(double power)
Add a given amount of power.
NiChange(double power, Ptr< Event > event)
Create a NiChange at the given time and the amount of NI change.
double GetPower() const
Return the power.
Ptr< Event > GetEvent() const
Return the event causes the corresponding NI change.
handles interference calculations
void SetNoiseFigure(double value)
Set the noise figure.
double m_noiseFigure
noise figure (linear)
Ptr< ErrorRateModel > GetErrorRateModel() const
Return the error rate model.
void AddForeignSignal(Time duration, RxPowerWattPerChannelBand &rxPower)
Add a non-Wifi signal to interference helper.
bool m_rxing
flag whether it is in receiving state
NiChanges::iterator AddNiChangeEvent(Time moment, NiChange change, NiChangesPerBand::iterator niIt)
Add NiChange to the list at the appropriate position and return the iterator of the new event.
std::map< WifiSpectrumBandInfo, NiChanges > NiChangesPerBand
Map of NiChanges per band.
double CalculateMuMimoPowerW(Ptr< const Event > event, const WifiSpectrumBandInfo &band) const
Calculate power of all other events preceding a given event that belong to the same MU-MIMO transmiss...
uint8_t m_numRxAntennas
the number of RX antennas in the corresponding receiver
bool IsBandInFrequencyRange(const WifiSpectrumBandInfo &band, const FrequencyRange &freqRange) const
Check whether a given band belongs to a given frequency range.
void DoDispose() override
Destructor implementation.
std::multimap< Time, NiChange > NiChanges
typedef for a multimap of NiChange
NiChangesPerBand m_niChanges
NI Changes for each band.
void UpdateBands(const std::vector< WifiSpectrumBandInfo > &bands, const FrequencyRange &freqRange)
Update the frequency bands that belongs to a given frequency range when the spectrum model is changed...
void SetErrorRateModel(const Ptr< ErrorRateModel > rate)
Set the error rate model for this interference helper.
bool HasBands() const
Check whether bands are already tracked by this interference helper.
double CalculatePayloadChunkSuccessRate(double snir, Time duration, const WifiTxVector &txVector, uint16_t staId=SU_STA_ID) const
Calculate the success rate of the payload chunk given the SINR, duration, and TXVECTOR.
Ptr< ErrorRateModel > m_errorRateModel
error rate model
Ptr< Event > Add(Ptr< const WifiPpdu > ppdu, Time duration, RxPowerWattPerChannelBand &rxPower, bool isStartHePortionRxing=false)
Add the PPDU-related signal to interference helper.
void NotifyRxStart()
Notify that RX has started.
NiChanges::iterator GetNextPosition(Time moment, NiChangesPerBand::iterator niIt)
Returns an iterator to the first NiChange that is later than moment.
FirstPowerPerBand m_firstPowers
first power of each band in watts
Time GetEnergyDuration(double energyW, const WifiSpectrumBandInfo &band)
bool IsSameMuMimoTransmission(Ptr< const Event > currentEvent, Ptr< const Event > otherEvent) const
Return whether another event is a MU-MIMO event that belongs to the same transmission and to the same...
double CalculateChunkSuccessRate(double snir, Time duration, WifiMode mode, const WifiTxVector &txVector, WifiPpduField field) const
Calculate the success rate of the chunk given the SINR, duration, and TXVECTOR.
double CalculatePayloadPer(Ptr< const Event > event, uint16_t channelWidth, NiChangesPerBand *nis, const WifiSpectrumBandInfo &band, uint16_t staId, std::pair< Time, Time > window) const
Calculate the error rate of the given PHY payload only in the provided time window (thus enabling per...
bool HasBand(const WifiSpectrumBandInfo &band) const
Check whether a given band is tracked by this interference helper.
void AddBand(const WifiSpectrumBandInfo &band)
Add a frequency band.
double CalculateNoiseInterferenceW(Ptr< Event > event, NiChangesPerBand &nis, const WifiSpectrumBandInfo &band) const
Calculate noise and interference power in W.
double CalculatePhyHeaderPer(Ptr< const Event > event, NiChangesPerBand *nis, uint16_t channelWidth, const WifiSpectrumBandInfo &band, WifiPpduField header) const
Calculate the error rate of the PHY header.
NiChanges::iterator GetPreviousPosition(Time moment, NiChangesPerBand::iterator niIt)
Returns an iterator to the last NiChange that is before than moment.
double CalculateSnr(Ptr< Event > event, uint16_t channelWidth, uint8_t nss, const WifiSpectrumBandInfo &band) const
Calculate the SNIR for the event (starting from now until the event end).
PhyEntity::SnrPer CalculatePhyHeaderSnrPer(Ptr< Event > event, uint16_t channelWidth, const WifiSpectrumBandInfo &band, WifiPpduField header) const
Calculate the SNIR at the start of the PHY header and accumulate all SNIR changes in the SNIR vector.
void AppendEvent(Ptr< Event > event, bool isStartHePortionRxing)
Append the given Event.
static TypeId GetTypeId()
Get the type ID.
void UpdateEvent(Ptr< Event > event, const RxPowerWattPerChannelBand &rxPower)
Update event to scale its received power (W) per band.
void NotifyRxEnd(Time endTime, const FrequencyRange &freqRange)
Notify that RX has ended.
double CalculatePhyHeaderSectionPsr(Ptr< const Event > event, NiChangesPerBand *nis, uint16_t channelWidth, const WifiSpectrumBandInfo &band, PhyEntity::PhyHeaderSections phyHeaderSections) const
Calculate the success rate of the PHY header sections for the provided event.
void SetNumberOfReceiveAntennas(uint8_t rx)
Set the number of RX antennas in the receiver corresponding to this interference helper.
PhyEntity::SnrPer CalculatePayloadSnrPer(Ptr< Event > event, uint16_t channelWidth, const WifiSpectrumBandInfo &band, uint16_t staId, std::pair< Time, Time > relativeMpduStartStop) const
Calculate the SNIR at the start of the payload and accumulate all SNIR changes in the SNIR vector for...
~InterferenceHelper() override
A base class which provides memory management and object aggregation.
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Smart pointer class similar to boost::intrusive_ptr.
Control the scheduling of simulation events.
static Time Now()
Return the current simulation virtual time.
Simulation virtual time values and global simulation resolution.
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
bool IsZero() const
Exactly equivalent to t == 0.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
represent a single transmission mode
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
static const Ptr< const PhyEntity > GetStaticPhyEntity(WifiModulationClass modulation)
Get the implemented PHY entity corresponding to the modulation class.
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Class that keeps track of all information about the current PHY operating channel.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
uint8_t GetNss(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the number of spatial streams.
uint16_t GetChannelWidth() const
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Time Now()
create an ns3::Time instance which contains the current simulation time.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
WifiPpduField
The type of PPDU field (grouped for convenience)
@ WIFI_PPDU_FIELD_DATA
data field
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double RatioToDb(double ratio)
Convert from ratio to dB.
std::ostream & operator<<(std::ostream &os, const Angles &a)
std::map< WifiSpectrumBandInfo, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Struct defining a frequency range between minFrequency (MHz) and maxFrequency (MHz).
uint16_t maxFrequency
the maximum frequency in MHz
uint16_t minFrequency
the minimum frequency in MHz
A struct for both SNR and PER.
WifiSpectrumBandInfo structure containing info about a spectrum band.
WifiSpectrumBandFrequencies frequencies
the start and stop frequencies of the band