18#include "ns3/he-ppdu.h" 
   20#include "ns3/packet.h" 
   21#include "ns3/simulator.h" 
   40      m_endTime(m_startTime + duration),
 
   41      m_rxPowerW(
std::move(rxPower))
 
 
   77                         [](
const auto& p1, 
const auto& p2) { return p1.second < p2.second; });
 
 
  102        auto band = currentRxPowerW.first;
 
  103        auto it = rxPower.find(band);
 
  104        if (it != rxPower.end())
 
  106            currentRxPowerW.second += it->second;
 
 
  120    os << 
"start=" << 
event.GetStartTime() << 
", end=" << 
event.GetEndTime()
 
  121       << 
", power=" << 
event.GetRxPower() << 
"W" 
  122       << 
", PPDU=" << 
event.GetPpdu();
 
 
  181                            .SetGroupName(
"Wifi")
 
 
  204                        bool isStartHePortionRxing)
 
  207    AppendEvent(event, freqRange, isStartHePortionRxing);
 
 
  224    Add(fakePpdu, duration, rxPowerW, freqRange);
 
 
  246    auto result = 
m_niChanges.insert({band, niChanges});
 
 
  270    std::vector<WifiSpectrumBandInfo> bandsToRemove{};
 
  277        const auto frequencies = it->first.frequencies;
 
  279            std::find_if(bands.cbegin(), bands.cend(), [frequencies](
const auto& item) {
 
  280                return frequencies == item.frequencies;
 
  281            }) != std::end(bands);
 
  285            bandsToRemove.emplace_back(it->first);
 
  288    for (
const auto& band : bandsToRemove)
 
  292    for (
const auto& band : bands)
 
 
  335    for (; i != niIt->second.end(); ++i)
 
  337        const auto noiseInterference = i->second.GetPower();
 
  339        if (noiseInterference < energy)
 
  344    return end > now ? end - now : 
Time{0};
 
 
  350                                bool isStartHePortionRxing)
 
  353    for (
const auto& [band, power] : 
event->GetRxPowerPerBand())
 
  357        Watt_u previousPowerStart{0.0};
 
  358        Watt_u previousPowerEnd{0.0};
 
  360        previousPowerStart = previousPowerPosition->second.GetPower();
 
  362        if (
const auto rxing = (
m_rxing.contains(freqRange) && 
m_rxing.at(freqRange)); !rxing)
 
  366            niIt->second.erase(++(niIt->second.begin()), ++previousPowerPosition);
 
  368        else if (isStartHePortionRxing)
 
  378        for (
auto i = 
first; i != last; ++i)
 
  380            i->second.AddPower(power);
 
 
  390    for (
const auto& [band, power] : rxPower)
 
  396        for (
auto i = 
first; i != last; ++i)
 
  398            i->second.AddPower(power);
 
  401    event->UpdateRxPowerW(rxPower);
 
 
  410    NS_LOG_FUNCTION(
this << signal << noiseInterference << channelWidth << +nss);
 
  412    static const double BOLTZMANN = 1.3803e-23;
 
  414    const auto Nt = BOLTZMANN * 290 * 
MHzToHz(channelWidth);
 
  417    Watt_u noise = noiseFloor + noiseInterference;
 
  418    auto snr = signal / noise; 
 
  419    NS_LOG_DEBUG(
"bandwidth=" << channelWidth << 
"MHz, signal=" << signal << 
"W, noise=" 
  420                              << noiseFloor << 
"W, interference=" << noiseInterference
 
  430        NS_LOG_DEBUG(
"SNR improvement thanks to diversity: " << 10 * std::log10(gain) << 
"dB");
 
 
  444    auto noiseInterference = firstPower_it->second;
 
  448    auto it = niIt->second.find(event->GetStartTime());
 
  452    for (; it != niIt->second.end() && it->first < now; ++it)
 
  455            (
event != it->second.GetEvent()))
 
  461        noiseInterference = it->second.GetPower() - 
event->GetRxPower(band) - muMimoPower;
 
  462        if (std::abs(noiseInterference) < std::numeric_limits<double>::epsilon())
 
  465            noiseInterference = 
Watt_u{0.0};
 
  468    it = niIt->second.find(event->GetStartTime());
 
  470    for (; it != niIt->second.end() && it->second.GetEvent() != event; ++it)
 
  476    while (++it != niIt->second.end() && it->second.GetEvent() != event)
 
  481    nis.insert({band, ni});
 
  483                  "CalculateNoiseInterferenceW returns negative value " << noiseInterference);
 
  484    return noiseInterference;
 
 
  493    auto it = niIt->second.begin();
 
  496    for (; it != niIt->second.end() && it->first < 
Simulator::Now(); ++it)
 
  506                    event->GetPpdu()->GetTxVector().GetHeMuUserInfoMap().cbegin()->first;
 
  507                const auto otherStaId = it->second.GetEvent()
 
  510                                            .GetHeMuUserInfoMap()
 
  513                if (staId == otherStaId)
 
  517                muMimoPower += it->second.GetEvent()->GetRxPower(band);
 
 
  536    auto nbits = 
static_cast<uint64_t
>(rate * duration.
GetSeconds());
 
 
  546                                                     uint16_t staId)
 const 
  552    const auto mode = txVector.
GetMode(staId);
 
  553    const auto rate = mode.
GetDataRate(txVector, staId);
 
  554    auto nbits = 
static_cast<uint64_t
>(rate * duration.
GetSeconds());
 
  555    nbits /= txVector.
GetNss(staId); 
 
 
 
  573                                        std::pair<Time, Time> window)
 const 
  575    NS_LOG_FUNCTION(
this << channelWidth << band << staId << window.first << window.second);
 
  577    const auto& niIt = nis->find(band)->second;
 
  578    auto j = niIt.cbegin();
 
  579    auto previous = j->first;
 
  581    const auto payloadMode = 
event->GetPpdu()->GetTxVector().GetMode(staId);
 
  582    auto phyPayloadStart = j->first;
 
  584        event->GetPpdu()->GetType() !=
 
  588                                         event->GetPpdu()->GetTxVector());
 
  594    const auto windowStart = phyPayloadStart + window.first;
 
  595    const auto windowEnd = phyPayloadStart + window.second;
 
  598    auto power = 
event->GetRxPower(band);
 
  599    while (++j != niIt.cend())
 
  601        Time current = j->first;
 
  602        NS_LOG_DEBUG(
"previous= " << previous << 
", current=" << current);
 
  607                                      event->GetPpdu()->GetTxVector().GetNss(staId));
 
  609        if (previous >= windowStart)
 
  612                                                    Min(windowEnd, current) - previous,
 
  613                                                    event->GetPpdu()->GetTxVector(),
 
  615            NS_LOG_DEBUG(
"Both previous and current point to the windowed payload: mode=" 
  616                         << payloadMode << 
", psr=" << psr);
 
  619        else if (current >= windowStart)
 
  622                                                    Min(windowEnd, current) - windowStart,
 
  623                                                    event->GetPpdu()->GetTxVector(),
 
  626                "previous is before windowed payload and current is in the windowed payload: mode=" 
  627                << payloadMode << 
", psr=" << psr);
 
  629        noiseInterference = j->second.GetPower() - power;
 
  632            muMimoPower += j->second.GetEvent()->GetRxPower(band);
 
  633            NS_LOG_DEBUG(
"PPDU belongs to same MU-MIMO transmission: muMimoPowerW=" << muMimoPower);
 
  635        noiseInterference -= muMimoPower;
 
  637        if (previous > windowEnd)
 
  640                                               << 
" after time window end=" << windowEnd);
 
  644    const auto per = 1.0 - psr;
 
 
  658    auto niIt = nis->find(band)->second;
 
  659    auto j = niIt.begin();
 
  662    Time stopLastSection;
 
  663    for (
const auto& section : phyHeaderSections)
 
  665        stopLastSection = 
Max(stopLastSection, section.second.first.second);
 
  668    auto previous = j->first;
 
  671    const auto power = 
event->GetRxPower(band);
 
  672    while (++j != niIt.end())
 
  674        auto current = j->first;
 
  675        NS_LOG_DEBUG(
"previous= " << previous << 
", current=" << current);
 
  677        const auto snr = 
CalculateSnr(power, noiseInterference, channelWidth, 1);
 
  678        for (
const auto& section : phyHeaderSections)
 
  680            const auto start = section.second.first.first;
 
  681            const auto stop = section.second.first.second;
 
  683            if (previous <= stop || current >= start)
 
  685                const auto duration = 
Min(stop, current) - 
Max(start, previous);
 
  686                if (duration.IsStrictlyPositive())
 
  690                                                     section.second.second,
 
  691                                                     event->GetPpdu()->GetTxVector(),
 
  694                                 << section.first << 
" [" << start << 
", " << stop << 
"] for " 
  695                                 << duration.As(
Time::NS) << 
": mode=" << section.second.second
 
  700        noiseInterference = j->second.GetPower() - power;
 
  702        if (previous > stopLastSection)
 
  704            NS_LOG_DEBUG(
"Stop: new previous=" << previous << 
" after stop of last section=" 
 
  720    auto niIt = nis->find(band)->second;
 
  725    for (
const auto& section :
 
  726         phyEntity->GetPhyHeaderSections(event->GetPpdu()->GetTxVector(), niIt.begin()->first))
 
  728        if (section.first == header)
 
  730            sections[header] = section.second;
 
  735    if (!sections.empty())
 
 
  747                                           std::pair<Time, Time> relativeMpduStartStop)
 const 
  749    NS_LOG_FUNCTION(
this << channelWidth << band << staId << relativeMpduStartStop.first
 
  750                         << relativeMpduStartStop.second);
 
  756                                  event->GetPpdu()->GetTxVector().GetNss(staId));
 
 
  775    return CalculateSnr(event->GetRxPower(band), noiseInterference, channelWidth, nss);
 
 
  787    const auto snr = 
CalculateSnr(event->GetRxPower(band), noiseInterference, channelWidth, 1);
 
 
  797InterferenceHelper::NiChanges::iterator
 
  800    return niIt->second.upper_bound(moment);
 
 
  803InterferenceHelper::NiChanges::iterator
 
  810InterferenceHelper::NiChanges::iterator
 
  813    return niIt->second.insert(
GetNextPosition(moment, niIt), {moment, change});
 
 
  837        m_firstPowers.find(niIt->first)->second = it->second.GetPower();
 
 
  847                       [&freqRange](
const auto& freqs) {
 
  848                           return ((freqs.second > MHzToHz(freqRange.minFrequency)) &&
 
  849                                   (freqs.first < MHzToHz(freqRange.maxFrequency)));
 
 
  859        (currentEvent->GetPpdu()->GetUid() == otherEvent->GetPpdu()->GetUid()))
 
  861        const auto currentTxVector = currentEvent->GetPpdu()->GetTxVector();
 
  862        const auto otherTxVector = otherEvent->GetPpdu()->GetTxVector();
 
  863        NS_ASSERT(currentTxVector.GetHeMuUserInfoMap().size() == 1);
 
  864        NS_ASSERT(otherTxVector.GetHeMuUserInfoMap().size() == 1);
 
  865        const auto currentUserInfo = currentTxVector.GetHeMuUserInfoMap().cbegin();
 
  866        const auto otherUserInfo = otherTxVector.GetHeMuUserInfoMap().cbegin();
 
  867        return (currentUserInfo->second.ru == otherUserInfo->second.ru);
 
 
 
 
 
handles interference calculations
Watt_u GetRxPower() const
Return the total received power.
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.
const RxPowerWattPerChannelBand & GetRxPowerPerBand() const
Return the received power (W) for all bands.
RxPowerWattPerChannelBand m_rxPowerW
received power in watts per band
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(Watt_u power)
Add a given amount of power.
NiChange(Watt_u power, Ptr< Event > event)
Create a NiChange at the given time and the amount of NI change.
Watt_u GetPower() const
Return the power.
Ptr< Event > GetEvent() const
Return the event causes the corresponding NI change.
handles interference calculations
double CalculatePhyHeaderPer(Ptr< const Event > event, NiChangesPerBand *nis, MHz_u channelWidth, const WifiSpectrumBandInfo &band, WifiPpduField header) const
Calculate the error rate of the PHY header.
void SetNoiseFigure(double value)
Set the noise figure.
Ptr< Event > Add(Ptr< const WifiPpdu > ppdu, Time duration, RxPowerWattPerChannelBand &rxPower, const FrequencyRange &freqRange, bool isStartHePortionRxing=false)
Add the PPDU-related signal to interference helper.
double m_noiseFigure
noise figure (linear)
std::map< FrequencyRange, bool > m_rxing
flag whether it is in receiving state for a given FrequencyRange
Ptr< ErrorRateModel > GetErrorRateModel() const
Return the error rate model.
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.
void NotifyRxStart(const FrequencyRange &freqRange)
Notify that RX has started.
NiChanges::iterator GetNextPosition(Time moment, NiChangesPerBand::iterator niIt) const
Returns an iterator to the first NiChange that is later than moment.
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
Time GetEnergyDuration(Watt_u energy, const WifiSpectrumBandInfo &band)
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.
void AddForeignSignal(Time duration, RxPowerWattPerChannelBand &rxPower, const FrequencyRange &freqRange)
Add a non-Wifi signal to interference helper.
PhyEntity::SnrPer CalculatePayloadSnrPer(Ptr< Event > event, MHz_u 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...
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
double CalculatePhyHeaderSectionPsr(Ptr< const Event > event, NiChangesPerBand *nis, MHz_u channelWidth, const WifiSpectrumBandInfo &band, PhyEntity::PhyHeaderSections phyHeaderSections) const
Calculate the success rate of the PHY header sections for the provided event.
FirstPowerPerBand m_firstPowers
first power of each band
PhyEntity::SnrPer CalculatePhyHeaderSnrPer(Ptr< Event > event, MHz_u 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.
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.
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.
Watt_u 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...
void AppendEvent(Ptr< Event > event, const FrequencyRange &freqRange, 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 RemoveBand(const WifiSpectrumBandInfo &band)
Remove a frequency band.
void NotifyRxEnd(Time endTime, const FrequencyRange &freqRange)
Notify that RX has ended.
Watt_u CalculateNoiseInterferenceW(Ptr< Event > event, NiChangesPerBand &nis, const WifiSpectrumBandInfo &band) const
Calculate noise and interference power.
void SetNumberOfReceiveAntennas(uint8_t rx)
Set the number of RX antennas in the receiver corresponding to this interference helper.
NiChanges::iterator GetPreviousPosition(Time moment, NiChangesPerBand::iterator niIt) const
Returns an iterator to the last NiChange that is before than moment.
double CalculateSnr(Ptr< Event > event, MHz_u channelWidth, uint8_t nss, const WifiSpectrumBandInfo &band) const
Calculate the SNIR for the event (starting from now until the event end).
double CalculatePayloadPer(Ptr< const Event > event, MHz_u 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...
~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.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
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(MHz_u channelWidth, Time 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.
MHz_u 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.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Time Now()
create an ns3::Time instance which contains the current simulation time.
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.
dB_u RatioToDb(double ratio)
Convert from ratio to dB.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
std::map< WifiSpectrumBandInfo, Watt_u > RxPowerWattPerChannelBand
A map of the received power for each band.
Hz_u MHzToHz(MHz_u val)
Convert from MHz to Hz.
double Watt_u
Watt weak type.
Struct defining a frequency range between minFrequency and maxFrequency.
A struct for both SNR and PER.
WifiSpectrumBandInfo structure containing info about a spectrum band.
std::vector< WifiSpectrumBandFrequencies > frequencies
the start and stop frequencies for each segment of the band