24#include "ns3/simulator.h"
26#include "ns3/packet.h"
43 m_txVector (txVector),
45 m_endTime (m_startTime + duration),
46 m_rxPowerW (
std::move (rxPower))
86 [] (
const std::pair<WifiSpectrumBand, double>& p1,
const std::pair<WifiSpectrumBand, double>& p2) {
87 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;
130 os <<
"start=" <<
event.GetStartTime () <<
", end=" <<
event.GetEndTime ()
131 <<
", TXVECTOR=" <<
event.GetTxVector ()
132 <<
", power=" <<
event.GetRxPowerW () <<
"W"
133 <<
", PPDU=" <<
event.GetPpdu ();
192 Ptr<Event> event = Create<Event> (ppdu, txVector, duration, std::move (rxPowerW));
205 Ptr<WifiPpdu> fakePpdu = Create<WifiPpdu> (Create<WifiPsdu> (Create<Packet> (0), hdr),
267 for (; i != niIt->second.end (); ++i)
269 double noiseInterferenceW = i->second.GetPower ();
271 if (noiseInterferenceW < energyW)
283 for (
auto const& it : event->GetRxPowerWPerBand ())
288 double previousPowerStart = 0;
289 double previousPowerEnd = 0;
291 previousPowerStart = previousPowerPosition->second.GetPower ();
297 niIt->second.erase (++(niIt->second.begin ()), ++previousPowerPosition);
299 else if (isStartOfdmaRxing)
308 for (
auto i =
first; i != last; ++i)
310 i->second.AddPower (it.second);
320 for (
auto const& it : rxPower)
327 for (
auto i =
first; i != last; ++i)
329 i->second.AddPower (it.second);
332 event->UpdateRxPowerW (rxPower);
338 NS_LOG_FUNCTION (
this << signal << noiseInterference << channelWidth << +nss);
340 static const double BOLTZMANN = 1.3803e-23;
342 double Nt = BOLTZMANN * 290 * channelWidth * 1e6;
345 double noise = noiseFloor + noiseInterference;
346 double snr = signal / noise;
347 NS_LOG_DEBUG (
"bandwidth(MHz)=" << channelWidth <<
", signal(W)= " << signal <<
", noise(W)=" << noiseFloor <<
", interference(W)=" << noiseInterference <<
", snr=" <<
RatioToDb(snr) <<
"dB");
355 NS_LOG_DEBUG (
"SNR improvement thanks to diversity: " << 10 * std::log10 (gain) <<
"dB");
367 double noiseInterferenceW = firstPower_it->second;
370 auto it = niIt->second.find (event->GetStartTime ());
371 for (; it != niIt->second.end () && it->first <
Simulator::Now (); ++it)
373 noiseInterferenceW = it->second.GetPower () -
event->GetRxPowerW (band);
375 it = niIt->second.find (event->GetStartTime ());
377 for (; it != niIt->second.end () && it->second.GetEvent () != event; ++it);
379 ni.emplace (event->GetStartTime (),
NiChange (0, event));
380 while (++it != niIt->second.end () && it->second.GetEvent () != event)
384 ni.emplace (event->GetEndTime (),
NiChange (0, event));
385 nis->insert ({band, ni});
386 NS_ASSERT_MSG (noiseInterferenceW >= 0,
"CalculateNoiseInterferenceW returns negative value " << noiseInterferenceW);
387 return noiseInterferenceW;
398 uint64_t nbits =
static_cast<uint64_t
> (rate * duration.
GetSeconds ());
411 uint64_t rate = mode.
GetDataRate (txVector, staId);
412 uint64_t nbits =
static_cast<uint64_t
> (rate * duration.
GetSeconds ());
413 nbits /= txVector.
GetNss (staId);
421 uint16_t staId, std::pair<Time, Time>
window)
const
425 const auto& niIt = nis->find (band)->second;
426 auto j = niIt.cbegin ();
427 Time previous = j->first;
428 WifiMode payloadMode =
event->GetTxVector ().GetMode (staId);
429 Time phyPayloadStart = j->first;
434 Time windowStart = phyPayloadStart +
window.first;
435 Time windowEnd = phyPayloadStart +
window.second;
437 double powerW =
event->GetRxPowerW (band);
438 while (++j != niIt.cend ())
440 Time current = j->first;
441 NS_LOG_DEBUG (
"previous= " << previous <<
", current=" << current);
443 double snr =
CalculateSnr (powerW, noiseInterferenceW, channelWidth, event->GetTxVector ().GetNss (staId));
445 if (previous >= windowStart)
448 NS_LOG_DEBUG (
"Both previous and current point to the windowed payload: mode=" << payloadMode <<
", psr=" << psr);
451 else if (current >= windowStart)
454 NS_LOG_DEBUG (
"previous is before windowed payload and current is in the windowed payload: mode=" << payloadMode <<
", psr=" << psr);
456 noiseInterferenceW = j->second.GetPower () - powerW;
458 if (previous > windowEnd)
460 NS_LOG_DEBUG (
"Stop: new previous=" << previous <<
" after time window end=" << windowEnd);
464 double per = 1 - psr;
475 auto niIt = nis->find (band)->second;
476 auto j = niIt.begin ();
480 for (
const auto & section : phyHeaderSections)
482 stopLastSection =
Max (stopLastSection, section.second.first.second);
485 Time previous = j->first;
487 double powerW =
event->GetRxPowerW (band);
488 while (++j != niIt.end ())
490 Time current = j->first;
491 NS_LOG_DEBUG (
"previous= " << previous <<
", current=" << current);
493 double snr =
CalculateSnr (powerW, noiseInterferenceW, channelWidth, 1);
494 for (
const auto & section : phyHeaderSections)
497 Time stop = section.second.first.second;
499 if (previous <= stop || current >=
start)
505 NS_LOG_DEBUG (
"Current NI change in " << section.first <<
" [" <<
start <<
", " << stop <<
"] for "
506 << duration.
As (
Time::NS) <<
": mode=" << section.second.second <<
", psr=" << psr);
510 noiseInterferenceW = j->second.GetPower () - powerW;
512 if (previous > stopLastSection)
514 NS_LOG_DEBUG (
"Stop: new previous=" << previous <<
" after stop of last section=" << stopLastSection);
527 auto niIt = nis->find (band)->second;
531 for (
const auto & section : phyEntity->GetPhyHeaderSections (event->GetTxVector (), niIt.begin ()->first))
533 if (section.first == header)
535 sections[header] = section.second;
540 if (!sections.empty () > 0)
548InterferenceHelper::CalculatePayloadSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band,
549 uint16_t staId, std::pair<Time, Time> relativeMpduStartStop) const
551 NS_LOG_FUNCTION (
this << channelWidth << band.first << band.second << staId << relativeMpduStartStop.first << relativeMpduStartStop.second);
553 double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band);
554 double snr = CalculateSnr (event->GetRxPowerW (band),
557 event->GetTxVector ().GetNss (staId));
562 double per = CalculatePayloadPer (event, channelWidth, &ni, band, staId, relativeMpduStartStop);
580InterferenceHelper::CalculatePhyHeaderSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band,
581 WifiPpduField header) const
585 double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band);
586 double snr = CalculateSnr (event->GetRxPowerW (band),
594 double per = CalculatePhyHeaderPer (event, &ni, channelWidth, band, header);
604 niIt->second.clear ();
612InterferenceHelper::NiChanges::iterator
615 return niIt->second.upper_bound (moment);
618InterferenceHelper::NiChanges::iterator
628InterferenceHelper::NiChanges::iterator
631 return niIt->second.insert (
GetNextPosition (moment, niIt), std::make_pair (moment, change));
handles interference calculations
WifiTxVector m_txVector
TXVECTOR.
Time m_startTime
start time
Ptr< const WifiPpdu > m_ppdu
PPDU.
void UpdateRxPowerW(const RxPowerWattPerChannelBand &rxPower)
Update the received power (W) for all bands, i.e.
Event(Ptr< const WifiPpdu > ppdu, const WifiTxVector &txVector, Time duration, RxPowerWattPerChannelBand &&rxPower)
Create an Event with the given parameters.
const RxPowerWattPerChannelBand & GetRxPowerWPerBand(void) const
Return the received power (W) for all bands.
const WifiTxVector & GetTxVector(void) const
Return the TXVECTOR of the PPDU.
Time GetDuration(void) const
Return the duration of the signal.
Ptr< const WifiPpdu > GetPpdu(void) const
Return the PPDU.
RxPowerWattPerChannelBand m_rxPowerW
received power in watts per band
Time GetStartTime(void) const
Return the start time of the signal.
double GetRxPowerW(void) const
Return the total received power (W).
Time GetEndTime(void) const
Return the end time of the signal.
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(void) const
Return the power.
Ptr< Event > GetEvent(void) 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)
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.
void EraseEvents(void)
Erase all events.
std::map< WifiSpectrumBand, NiChanges > NiChangesPerBand
Map of NiChanges per band.
uint8_t m_numRxAntennas
the number of RX antennas in the corresponding receiver
void NotifyRxEnd(Time endTime)
Notify that RX has ended.
double CalculateNoiseInterferenceW(Ptr< Event > event, NiChangesPerBand *nis, WifiSpectrumBand band) const
Calculate noise and interference power in W.
void SetErrorRateModel(const Ptr< ErrorRateModel > rate)
Set the error rate model for this interference helper.
std::multimap< Time, NiChange > NiChanges
typedef for a multimap of NiChange
Time GetEnergyDuration(double energyW, WifiSpectrumBand band)
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
void AppendEvent(Ptr< Event > event, bool isStartOfdmaRxing)
Append the given Event.
Ptr< ErrorRateModel > GetErrorRateModel(void) const
Return the error rate model.
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.
double CalculateSnr(Ptr< Event > event, uint16_t channelWidth, uint8_t nss, WifiSpectrumBand band) const
Calculate the SNIR for the event (starting from now until the event end).
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, WifiSpectrumBand 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...
NiChanges::iterator GetPreviousPosition(Time moment, NiChangesPerBand::iterator niIt)
Returns an iterator to the last NiChange that is before than moment.
void RemoveBands(void)
Remove the frequency bands.
double CalculatePhyHeaderSectionPsr(Ptr< const Event > event, NiChangesPerBand *nis, uint16_t channelWidth, WifiSpectrumBand band, PhyEntity::PhyHeaderSections phyHeaderSections) const
Calculate the success rate of the PHY header sections for the provided event.
Ptr< Event > Add(Ptr< const WifiPpdu > ppdu, const WifiTxVector &txVector, Time duration, RxPowerWattPerChannelBand &rxPower, bool isStartOfdmaRxing=false)
Add the PPDU-related signal to interference helper.
void UpdateEvent(Ptr< Event > event, const RxPowerWattPerChannelBand &rxPower)
Update event to scale its received power (W) per band.
void SetNumberOfReceiveAntennas(uint8_t rx)
Set the number of RX antennas in the receiver corresponding to this interference helper.
void AddBand(WifiSpectrumBand band)
Add a frequency band.
double CalculatePhyHeaderPer(Ptr< const Event > event, NiChangesPerBand *nis, uint16_t channelWidth, WifiSpectrumBand band, WifiPpduField header) const
Calculate the error rate of the PHY header.
NiChangesPerBand m_niChangesPerBand
NI Changes for each band.
std::map< WifiSpectrumBand, double > m_firstPowerPerBand
first power of each band in watts
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(void)
Return the current simulation virtual time.
Simulation virtual time values and global simulation resolution.
bool IsStrictlyPositive(void) const
Exactly equivalent to t > 0.
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
bool IsZero(void) const
Exactly equivalent to t == 0.
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
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)
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(void) 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...
int64x64_t Max(const int64x64_t &a, const int64x64_t &b)
Maximum.
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
#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 ",...
Time Now(void)
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::pair< uint32_t, uint32_t > WifiSpectrumBand
typedef for a pair of start and stop sub-band indexes
std::ostream & operator<<(std::ostream &os, const Angles &a)
std::map< WifiSpectrumBand, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
A struct for both SNR and PER.
double snr
SNR in linear scale.