24 #include "ns3/simulator.h"
26 #include "ns3/packet.h"
43 m_txVector (txVector),
45 m_endTime (m_startTime + duration),
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, rxPowerW);
205 Ptr<WifiPpdu> fakePpdu = Create<WifiPpdu> (Create<WifiPsdu> (Create<Packet> (0), hdr),
266 for (; i != ni_it->second.end (); ++i)
268 double noiseInterferenceW = i->second.GetPower ();
270 if (noiseInterferenceW < energyW)
283 for (
auto const& it : rxPowerWattPerChannelBand)
288 double previousPowerStart = 0;
289 double previousPowerEnd = 0;
290 previousPowerStart =
GetPreviousPosition (event->GetStartTime (), band)->second.GetPower ();
296 ni_it->second.erase (++(ni_it->second.begin ()),
GetNextPosition (event->GetStartTime (), band));
298 else if (isStartOfdmaRxing)
307 for (
auto i =
first; i != last; ++i)
309 i->second.AddPower (it.second);
319 for (
auto const& it : rxPower)
326 for (
auto i =
first; i != last; ++i)
328 i->second.AddPower (it.second);
331 event->UpdateRxPowerW (rxPower);
337 NS_LOG_FUNCTION (
this << signal << noiseInterference << channelWidth << +nss);
339 static const double BOLTZMANN = 1.3803e-23;
341 double Nt = BOLTZMANN * 290 * channelWidth * 1e6;
344 double noise = noiseFloor + noiseInterference;
345 double snr = signal / noise;
346 NS_LOG_DEBUG (
"bandwidth(MHz)=" << channelWidth <<
", signal(W)= " << signal <<
", noise(W)=" << noiseFloor <<
", interference(W)=" << noiseInterference <<
", snr=" <<
RatioToDb(snr) <<
"dB");
354 NS_LOG_DEBUG (
"SNR improvement thanks to diversity: " << 10 * std::log10 (gain) <<
"dB");
366 double noiseInterferenceW = firstPower_it->second;
369 auto it = ni_it->second.find (event->GetStartTime ());
370 for (; it != ni_it->second.end () && it->first <
Simulator::Now (); ++it)
372 noiseInterferenceW = it->second.GetPower () -
event->GetRxPowerW (band);
374 it = ni_it->second.find (event->GetStartTime ());
376 for (; it != ni_it->second.end () && it->second.GetEvent () != event; ++it);
378 ni.emplace (event->GetStartTime (),
NiChange (0, event));
379 while (++it != ni_it->second.end () && it->second.GetEvent () != event)
383 ni.emplace (event->GetEndTime (),
NiChange (0, event));
384 nis->insert ({band, ni});
385 NS_ASSERT_MSG (noiseInterferenceW >= 0,
"CalculateNoiseInterferenceW returns negative value " << noiseInterferenceW);
386 return noiseInterferenceW;
397 uint64_t nbits =
static_cast<uint64_t
> (rate * duration.
GetSeconds ());
410 uint64_t rate = mode.
GetDataRate (txVector, staId);
411 uint64_t nbits =
static_cast<uint64_t
> (rate * duration.
GetSeconds ());
412 nbits /= txVector.
GetNss (staId);
420 uint16_t staId, std::pair<Time, Time>
window)
const
424 auto ni_it = nis->find (band)->second;
425 auto j = ni_it.begin ();
426 Time previous = j->first;
427 WifiMode payloadMode =
event->GetTxVector ().GetMode (staId);
428 Time phyPayloadStart = j->first;
433 Time windowStart = phyPayloadStart +
window.first;
434 Time windowEnd = phyPayloadStart +
window.second;
436 double powerW =
event->GetRxPowerW (band);
437 while (++j != ni_it.end ())
439 Time current = j->first;
440 NS_LOG_DEBUG (
"previous= " << previous <<
", current=" << current);
442 double snr =
CalculateSnr (powerW, noiseInterferenceW, channelWidth, event->GetTxVector ().GetNss (staId));
444 if (previous >= windowStart)
447 NS_LOG_DEBUG (
"Both previous and current point to the windowed payload: mode=" << payloadMode <<
", psr=" << psr);
450 else if (current >= windowStart)
453 NS_LOG_DEBUG (
"previous is before windowed payload and current is in the windowed payload: mode=" << payloadMode <<
", psr=" << psr);
455 noiseInterferenceW = j->second.GetPower () - powerW;
457 if (previous > windowEnd)
459 NS_LOG_DEBUG (
"Stop: new previous=" << previous <<
" after time window end=" << windowEnd);
463 double per = 1 - psr;
474 auto ni_it = nis->find (band)->second;
475 auto j = ni_it.begin ();
479 for (
const auto & section : phyHeaderSections)
481 stopLastSection =
Max (stopLastSection, section.second.first.second);
484 Time previous = j->first;
486 double powerW =
event->GetRxPowerW (band);
487 while (++j != ni_it.end ())
489 Time current = j->first;
490 NS_LOG_DEBUG (
"previous= " << previous <<
", current=" << current);
492 double snr =
CalculateSnr (powerW, noiseInterferenceW, channelWidth, 1);
493 for (
const auto & section : phyHeaderSections)
496 Time stop = section.second.first.second;
498 if (previous <= stop || current >=
start)
504 NS_LOG_DEBUG (
"Current NI change in " << section.first <<
" [" <<
start <<
", " << stop <<
"] for "
505 << duration.
As (
Time::NS) <<
": mode=" << section.second.second <<
", psr=" << psr);
509 noiseInterferenceW = j->second.GetPower () - powerW;
511 if (previous > stopLastSection)
513 NS_LOG_DEBUG (
"Stop: new previous=" << previous <<
" after stop of last section=" << stopLastSection);
526 auto ni_it = nis->find (band)->second;
530 for (
const auto & section : phyEntity->GetPhyHeaderSections (event->GetTxVector (), ni_it.begin ()->first))
532 if (section.first == header)
534 sections[header] = section.second;
539 if (!sections.empty () > 0)
547 InterferenceHelper::CalculatePayloadSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band,
548 uint16_t staId, std::pair<Time, Time> relativeMpduStartStop) const
550 NS_LOG_FUNCTION (
this << channelWidth << band.first << band.second << staId << relativeMpduStartStop.first << relativeMpduStartStop.second);
552 double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band);
553 double snr = CalculateSnr (event->GetRxPowerW (band),
556 event->GetTxVector ().GetNss (staId));
561 double per = CalculatePayloadPer (event, channelWidth, &ni, band, staId, relativeMpduStartStop);
579 InterferenceHelper::CalculatePhyHeaderSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band,
580 WifiPpduField header) const
584 double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni, band);
585 double snr = CalculateSnr (event->GetRxPowerW (band),
593 double per = CalculatePhyHeaderPer (event, &ni, channelWidth, band, header);
611 InterferenceHelper::NiChanges::iterator
616 return it->second.upper_bound (moment);
619 InterferenceHelper::NiChanges::iterator
629 InterferenceHelper::NiChanges::iterator
634 return it->second.insert (
GetNextPosition (moment, band), std::make_pair (moment, change));
handles interference calculations
RxPowerWattPerChannelBand GetRxPowerWPerBand(void) const
Return the received power (W) for all bands.
WifiTxVector m_txVector
TXVECTOR.
Time m_startTime
start time
Ptr< const WifiPpdu > m_ppdu
PPDU.
void UpdateRxPowerW(RxPowerWattPerChannelBand rxPower)
Update the received power (W) for all bands, i.e.
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.
Event(Ptr< const WifiPpdu > ppdu, const WifiTxVector &txVector, Time duration, RxPowerWattPerChannelBand rxPower)
Create an Event with the given parameters.
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)
NiChanges::iterator AddNiChangeEvent(Time moment, NiChange change, WifiSpectrumBand band)
Add NiChange to the list at the appropriate position and return the iterator of the new event.
bool m_rxing
flag whether it is in receiving state
void EraseEvents(void)
Erase all events.
std::map< WifiSpectrumBand, NiChanges > NiChangesPerBand
Map of NiChanges per band.
void UpdateEvent(Ptr< Event > event, RxPowerWattPerChannelBand rxPower)
Update event to scale its received power (W) per band.
uint8_t m_numRxAntennas
the number of RX antennas in the corresponding receiver
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 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)
NiChanges::iterator GetPreviousPosition(Time moment, WifiSpectrumBand band)
Returns an iterator to the last NiChange that is before than moment.
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 AddForeignSignal(Time duration, RxPowerWattPerChannelBand rxPower)
Add a non-Wifi signal to interference helper.
Ptr< ErrorRateModel > m_errorRateModel
error rate model
void AppendEvent(Ptr< Event > event, bool isStartOfdmaRxing)
Append the given Event.
NiChanges::iterator GetNextPosition(Time moment, WifiSpectrumBand band)
Returns an iterator to the first NiChange that is later than moment.
Ptr< ErrorRateModel > GetErrorRateModel(void) const
Return the error rate model.
void NotifyRxStart()
Notify that RX has started.
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...
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.
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::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.