24 #include "ns3/simulator.h"
26 #include "ns3/packet.h"
45 m_txVector (txVector),
47 m_endTime (m_startTime + duration),
48 m_rxPowerW (std::move (rxPower))
88 [] (
const std::pair<WifiSpectrumBand, double>& p1,
const std::pair<WifiSpectrumBand, double>& p2) {
89 return p1.second < p2.second;
121 auto band = currentRxPowerW.first;
122 auto it = rxPower.find (band);
123 if (it != rxPower.end ())
125 currentRxPowerW.second += it->second;
132 os <<
"start=" <<
event.GetStartTime () <<
", end=" <<
event.GetEndTime ()
133 <<
", TXVECTOR=" <<
event.GetTxVector ()
134 <<
", power=" <<
event.GetRxPowerW () <<
"W"
135 <<
", PPDU=" <<
event.GetPpdu ();
196 .SetGroupName (
"Wifi")
213 Ptr<Event> event = Create<Event> (ppdu, txVector, duration, std::move (rxPowerW));
226 Ptr<WifiPpdu> fakePpdu = Create<WifiPpdu> (Create<WifiPsdu> (Create<Packet> (0), hdr),
288 for (; i != niIt->second.end (); ++i)
290 double noiseInterferenceW = i->second.GetPower ();
292 if (noiseInterferenceW < energyW)
304 for (
auto const& it : event->GetRxPowerWPerBand ())
309 double previousPowerStart = 0;
310 double previousPowerEnd = 0;
312 previousPowerStart = previousPowerPosition->second.GetPower ();
318 niIt->second.erase (++(niIt->second.begin ()), ++previousPowerPosition);
320 else if (isStartOfdmaRxing)
329 for (
auto i =
first; i != last; ++i)
331 i->second.AddPower (it.second);
341 for (
auto const& it : rxPower)
348 for (
auto i =
first; i != last; ++i)
350 i->second.AddPower (it.second);
353 event->UpdateRxPowerW (rxPower);
359 NS_LOG_FUNCTION (
this << signal << noiseInterference << channelWidth << +nss);
361 static const double BOLTZMANN = 1.3803e-23;
363 double Nt = BOLTZMANN * 290 * channelWidth * 1e6;
366 double noise = noiseFloor + noiseInterference;
367 double snr = signal / noise;
368 NS_LOG_DEBUG (
"bandwidth(MHz)=" << channelWidth <<
", signal(W)= " << signal <<
", noise(W)=" << noiseFloor <<
", interference(W)=" << noiseInterference <<
", snr=" <<
RatioToDb(snr) <<
"dB");
376 NS_LOG_DEBUG (
"SNR improvement thanks to diversity: " << 10 * std::log10 (gain) <<
"dB");
388 double noiseInterferenceW = firstPower_it->second;
391 auto it = niIt->second.find (event->GetStartTime ());
392 for (; it != niIt->second.end () && it->first <
Simulator::Now (); ++it)
394 noiseInterferenceW = it->second.GetPower () -
event->GetRxPowerW (band);
396 it = niIt->second.find (event->GetStartTime ());
398 for (; it != niIt->second.end () && it->second.GetEvent () != event; ++it);
400 ni.emplace (event->GetStartTime (),
NiChange (0, event));
401 while (++it != niIt->second.end () && it->second.GetEvent () != event)
405 ni.emplace (event->GetEndTime (),
NiChange (0, event));
406 nis->insert ({band, ni});
407 NS_ASSERT_MSG (noiseInterferenceW >= 0,
"CalculateNoiseInterferenceW returns negative value " << noiseInterferenceW);
408 return noiseInterferenceW;
419 uint64_t nbits =
static_cast<uint64_t
> (rate * duration.
GetSeconds ());
432 uint64_t rate = mode.
GetDataRate (txVector, staId);
433 uint64_t nbits =
static_cast<uint64_t
> (rate * duration.
GetSeconds ());
434 nbits /= txVector.
GetNss (staId);
442 uint16_t staId, std::pair<Time, Time>
window)
const
446 const auto& niIt = nis->find (band)->second;
447 auto j = niIt.cbegin ();
448 Time previous = j->first;
449 WifiMode payloadMode =
event->GetTxVector ().GetMode (staId);
450 Time phyPayloadStart = j->first;
455 Time windowStart = phyPayloadStart +
window.first;
456 Time windowEnd = phyPayloadStart +
window.second;
458 double powerW =
event->GetRxPowerW (band);
459 while (++j != niIt.cend ())
461 Time current = j->first;
462 NS_LOG_DEBUG (
"previous= " << previous <<
", current=" << current);
464 double snr =
CalculateSnr (powerW, noiseInterferenceW, channelWidth, event->GetTxVector ().GetNss (staId));
466 if (previous >= windowStart)
469 NS_LOG_DEBUG (
"Both previous and current point to the windowed payload: mode=" << payloadMode <<
", psr=" << psr);
472 else if (current >= windowStart)
475 NS_LOG_DEBUG (
"previous is before windowed payload and current is in the windowed payload: mode=" << payloadMode <<
", psr=" << psr);
477 noiseInterferenceW = j->second.GetPower () - powerW;
479 if (previous > windowEnd)
481 NS_LOG_DEBUG (
"Stop: new previous=" << previous <<
" after time window end=" << windowEnd);
485 double per = 1 - psr;
496 auto niIt = nis->find (band)->second;
497 auto j = niIt.begin ();
501 for (
const auto & section : phyHeaderSections)
503 stopLastSection =
Max (stopLastSection, section.second.first.second);
506 Time previous = j->first;
508 double powerW =
event->GetRxPowerW (band);
509 while (++j != niIt.end ())
511 Time current = j->first;
512 NS_LOG_DEBUG (
"previous= " << previous <<
", current=" << current);
514 double snr =
CalculateSnr (powerW, noiseInterferenceW, channelWidth, 1);
515 for (
const auto & section : phyHeaderSections)
518 Time stop = section.second.first.second;
520 if (previous <= stop || current >=
start)
526 NS_LOG_DEBUG (
"Current NI change in " << section.first <<
" [" <<
start <<
", " << stop <<
"] for "
527 << duration.
As (
Time::NS) <<
": mode=" << section.second.second <<
", psr=" << psr);
531 noiseInterferenceW = j->second.GetPower () - powerW;
533 if (previous > stopLastSection)
535 NS_LOG_DEBUG (
"Stop: new previous=" << previous <<
" after stop of last section=" << stopLastSection);
548 auto niIt = nis->find (band)->second;
552 for (
const auto & section : phyEntity->GetPhyHeaderSections (event->GetTxVector (), niIt.begin ()->first))
554 if (section.first == header)
556 sections[header] = section.second;
561 if (!sections.empty () > 0)
569 InterferenceHelper::CalculatePayloadSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band,
570 uint16_t staId, std::pair<Time, Time> relativeMpduStartStop) const
572 NS_LOG_FUNCTION (
this << channelWidth << band.first << band.second << staId << relativeMpduStartStop.first << relativeMpduStartStop.second);
574 double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band);
575 double snr = CalculateSnr (event->GetRxPowerW (band),
578 event->GetTxVector ().GetNss (staId));
583 double per = CalculatePayloadPer (event, channelWidth, &ni, band, staId, relativeMpduStartStop);
601 InterferenceHelper::CalculatePhyHeaderSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band,
602 WifiPpduField header) const
606 double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band);
607 double snr = CalculateSnr (event->GetRxPowerW (band),
615 double per = CalculatePhyHeaderPer (event, &ni, channelWidth, band, header);
625 niIt->second.clear ();
633 InterferenceHelper::NiChanges::iterator
636 return niIt->second.upper_bound (moment);
639 InterferenceHelper::NiChanges::iterator
649 InterferenceHelper::NiChanges::iterator
652 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.
void DoDispose(void) override
Destructor implementation.
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.
static TypeId GetTypeId(void)
Get the type ID.
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.
virtual ~InterferenceHelper()
NiChangesPerBand m_niChangesPerBand
NI Changes for each band.
std::map< WifiSpectrumBand, double > m_firstPowerPerBand
first power of each band in watts
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(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.
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)
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 ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
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::map< WifiSpectrumBand, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
std::ostream & operator<<(std::ostream &os, const Angles &a)
A struct for both SNR and PER.
double snr
SNR in linear scale.