A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lora-interference-helper.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 University of Padova
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Davide Magrin <magrinda@dei.unipd.it>
7 */
8
10
11#include "lora-utils.h"
12
13#include "ns3/simulator.h"
14
15namespace ns3
16{
17namespace lorawan
18{
19
20NS_LOG_COMPONENT_DEFINE("LoraInterferenceHelper");
21
22/***************************************
23 * LoraInterferenceHelper::Event *
24 ***************************************/
25
26// Event Constructor
28 double rxPowerdBm,
29 uint8_t spreadingFactor,
30 Ptr<Packet> packet,
31 uint32_t frequencyHz)
32 : m_startTime(Now()),
33 m_endTime(m_startTime + duration),
34 m_sf(spreadingFactor),
35 m_rxPowerdBm(rxPowerdBm),
36 m_packet(packet),
37 m_frequencyHz(frequencyHz)
38{
39 // NS_LOG_FUNCTION_NOARGS ();
40}
41
42// Event Destructor
44{
45 // NS_LOG_FUNCTION_NOARGS ();
46}
47
48// Getters
49Time
54
55Time
60
61Time
66
67double
72
73uint8_t
78
84
90
91void
92LoraInterferenceHelper::Event::Print(std::ostream& stream) const
93{
94 stream << "(" << m_startTime.As(Time::S) << " - " << m_endTime.As(Time::S) << "), SF"
95 << unsigned(m_sf) << ", " << m_rxPowerdBm << " dBm, " << m_frequencyHz << " Hz";
96}
97
98std::ostream&
99operator<<(std::ostream& os, const LoraInterferenceHelper::Event& event)
100{
101 event.Print(os);
102
103 return os;
104}
105
106/****************************
107 * LoraInterferenceHelper *
108 ****************************/
109// This collision matrix can be used for comparisons with the performance of Aloha
110// systems, where collisions imply the loss of both packets.
111double inf = std::numeric_limits<double>::max();
112std::vector<std::vector<double>> LoraInterferenceHelper::collisionSnirAloha = {
113 // 7 8 9 10 11 12
114 {inf, -inf, -inf, -inf, -inf, -inf}, // SF7
115 {-inf, inf, -inf, -inf, -inf, -inf}, // SF8
116 {-inf, -inf, inf, -inf, -inf, -inf}, // SF9
117 {-inf, -inf, -inf, inf, -inf, -inf}, // SF10
118 {-inf, -inf, -inf, -inf, inf, -inf}, // SF11
119 {-inf, -inf, -inf, -inf, -inf, inf} // SF12
120};
121
122// LoRa Collision Matrix (Goursaud)
123// Values are inverted w.r.t. the paper since here we interpret this as an
124// _isolation_ matrix instead of a cochannel _rejection_ matrix like in
125// Goursaud's paper.
126std::vector<std::vector<double>> LoraInterferenceHelper::collisionSnirGoursaud = {
127 // SF7 SF8 SF9 SF10 SF11 SF12
128 {6, -16, -18, -19, -19, -20}, // SF7
129 {-24, 6, -20, -22, -22, -22}, // SF8
130 {-27, -27, 6, -23, -25, -25}, // SF9
131 {-30, -30, -30, 6, -26, -28}, // SF10
132 {-33, -33, -33, -33, 6, -29}, // SF11
133 {-36, -36, -36, -36, -36, 6} // SF12
134};
135
138
139void
155
163
168
170
173 double rxPower,
174 uint8_t spreadingFactor,
175 Ptr<Packet> packet,
176 uint32_t frequencyHz)
177{
178 NS_LOG_FUNCTION(this << duration.As(Time::MS) << rxPower << unsigned(spreadingFactor) << packet
179 << frequencyHz);
180
181 // Create an event based on the parameters
184 rxPower,
185 spreadingFactor,
186 packet,
187 frequencyHz);
188
189 // Add the event to the list
190 m_events.push_back(event);
191
192 // Clean the event list
193 if (m_events.size() > 100)
194 {
196 }
197
198 return event;
199}
200
201void
203{
204 NS_LOG_FUNCTION(this);
205
206 // Cycle the events, and clean up if an event is old.
207 for (auto it = m_events.begin(); it != m_events.end();)
208 {
209 if ((*it)->GetEndTime() + oldEventThreshold < Now())
210 {
211 it = m_events.erase(it);
212 }
213 else
214 {
215 it++;
216 }
217 }
218}
219
220std::list<Ptr<LoraInterferenceHelper::Event>>
225
226void
228{
230
231 stream << "Currently registered events:" << std::endl;
232
233 for (auto it = m_events.begin(); it != m_events.end(); it++)
234 {
235 (*it)->Print(stream);
236 stream << std::endl;
237 }
238}
239
240uint8_t
242{
243 NS_LOG_FUNCTION(this << event);
244
245 NS_LOG_INFO("Current number of events in LoraInterferenceHelper: " << m_events.size());
246
247 // We want to see the interference affecting this event: cycle through events
248 // that overlap with this one and see whether it survives the interference or
249 // not.
250
251 // Gather information about the event
252 double rxPowerDbm = event->GetRxPowerdBm();
253 uint8_t sf = event->GetSpreadingFactor();
254 uint32_t frequencyHz = event->GetFrequency();
255
256 // Handy information about the time frame when the packet was received
257 Time now = Now();
258 Time duration = event->GetDuration();
259 Time packetStartTime = now - duration;
260
261 // Get the list of interfering events
262 std::list<Ptr<LoraInterferenceHelper::Event>>::iterator it;
263
264 // Energy for interferers of various SFs
265 std::vector<double> cumulativeInterferenceEnergy(6, 0);
266
267 // Cycle over the events
268 for (it = m_events.begin(); it != m_events.end();)
269 {
270 // Pointer to the current interferer
271 Ptr<LoraInterferenceHelper::Event> interferer = *it;
272
273 // Only consider the current event if the channel is the same: we
274 // assume there's no interchannel interference. Also skip the current
275 // event if it's the same that we want to analyze.
276 if (!(interferer->GetFrequency() == frequencyHz) || interferer == event)
277 {
278 NS_LOG_DEBUG("Different channel or same event");
279 it++;
280 continue; // Continues from the first line inside the for cycle
281 }
282
283 NS_LOG_DEBUG("Interferer on same channel");
284
285 // Gather information about this interferer
286 uint8_t interfererSf = interferer->GetSpreadingFactor();
287 double interfererPower = interferer->GetRxPowerdBm();
288 Time interfererStartTime = interferer->GetStartTime();
289 Time interfererEndTime = interferer->GetEndTime();
290
291 NS_LOG_INFO("Found an interferer: sf = " << unsigned(interfererSf)
292 << ", power = " << interfererPower
293 << ", start time = " << interfererStartTime
294 << ", end time = " << interfererEndTime);
295
296 // Compute the fraction of time the two events are overlapping
297 Time overlap = GetOverlapTime(event, interferer);
298
299 NS_LOG_DEBUG("The two events overlap for " << overlap.As(Time::S));
300
301 double interfererPowerW = DbmToW(interfererPower);
302 // Energy [J] = Time [s] * Power [W]
303 double interferenceEnergy = overlap.GetSeconds() * interfererPowerW;
304 cumulativeInterferenceEnergy.at(unsigned(interfererSf) - 7) += interferenceEnergy;
305 NS_LOG_DEBUG("Interferer power in W: " << interfererPowerW);
306 NS_LOG_DEBUG("Interference energy: " << interferenceEnergy);
307 it++;
308 }
309
310 // For each spreading factor, check if there was destructive interference
311 for (auto currentSf = uint8_t(7); currentSf <= uint8_t(12); currentSf++)
312 {
313 NS_LOG_DEBUG("Cumulative Interference Energy: "
314 << cumulativeInterferenceEnergy.at(unsigned(currentSf) - 7));
315
316 // Use the computed cumulativeInterferenceEnergy to determine whether the
317 // interference with this spreading factor destroys the packet
318 double signalPowerW = DbmToW(rxPowerDbm);
319 double signalEnergy = duration.GetSeconds() * signalPowerW;
320 NS_LOG_DEBUG("Signal power in W: " << signalPowerW);
321 NS_LOG_DEBUG("Signal energy: " << signalEnergy);
322
323 // Check whether the packet survives the interference of this spreading factor
324 double snirIsolation = m_collisionSnir[unsigned(sf) - 7][unsigned(currentSf) - 7];
325 NS_LOG_DEBUG("The needed isolation to survive is " << snirIsolation << " dB");
326 double snir =
327 10 * log10(signalEnergy / cumulativeInterferenceEnergy.at(unsigned(currentSf) - 7));
328 NS_LOG_DEBUG("The current SNIR is " << snir << " dB");
329
330 if (snir >= snirIsolation)
331 {
332 // Move on and check the rest of the interferers
333 NS_LOG_DEBUG("Packet survived interference with SF " << currentSf);
334 }
335 else
336 {
337 NS_LOG_DEBUG("Packet destroyed by interference with SF" << unsigned(currentSf));
338
339 return currentSf;
340 }
341 }
342 // If we get to here, it means that the packet survived all interference
343 NS_LOG_DEBUG("Packet survived all interference");
344
345 // Since the packet was not destroyed, we return 0.
346 return uint8_t(0);
347}
348
349void
356
357Time
360{
362
363 // Create the value we will return later
364 Time overlap;
365
366 // Get handy values
367 Time s1 = event1->GetStartTime(); // Start times
368 Time s2 = event2->GetStartTime();
369 Time e1 = event1->GetEndTime(); // End times
370 Time e2 = event2->GetEndTime();
371
372 // Non-overlapping events
373 if (e1 <= s2 || e2 <= s1)
374 {
375 overlap = Time(0);
376 }
377 // event1 before event2
378 else if (s1 < s2)
379 {
380 if (e2 < e1)
381 {
382 overlap = e2 - s2;
383 }
384 else
385 {
386 overlap = e1 - s2;
387 }
388 }
389 // event2 before event1 or they start at the same time (s1 = s2)
390 else
391 {
392 if (e1 < e2)
393 {
394 overlap = e1 - s1;
395 }
396 else
397 {
398 overlap = e2 - s1;
399 }
400 }
401
402 return overlap;
403}
404
405} // namespace lorawan
406} // namespace ns3
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:408
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:398
@ MS
millisecond
Definition nstime.h:107
@ S
second
Definition nstime.h:106
A class representing a signal in time.
double GetRxPowerdBm() const
Get the power of the event.
Time m_startTime
The time this signal begins (at the device).
Event(Time duration, double rxPowerdBm, uint8_t spreadingFactor, Ptr< Packet > packet, uint32_t frequencyHz)
Construct a new interference signal Event object.
Time GetStartTime() const
Get the starting time of the event.
Time GetEndTime() const
Get the ending time of the event.
uint8_t GetSpreadingFactor() const
Get the spreading factor used by this signal.
Time GetDuration() const
Get the duration of the event.
Time m_endTime
The time this signal ends (at the device).
uint8_t m_sf
The spreading factor of this signal.
uint32_t m_frequencyHz
The carrier frequency [Hz] this event was on.
Ptr< Packet > GetPacket() const
Get the packet this event was generated for.
void Print(std::ostream &stream) const
Print the current event in a human readable form.
Ptr< Packet > m_packet
The packet this event was generated for.
uint32_t GetFrequency() const
Get the frequency this event was on.
double m_rxPowerdBm
The power of this event in dBm (at the device).
static std::vector< std::vector< double > > collisionSnirGoursaud
GOURSAUD collision matrix.
static Time oldEventThreshold
The threshold after which an event is considered old and removed from the list.
Time GetOverlapTime(Ptr< LoraInterferenceHelper::Event > event1, Ptr< LoraInterferenceHelper::Event > event2)
Compute the time duration in which two given events are overlapping.
Ptr< LoraInterferenceHelper::Event > Add(Time duration, double rxPower, uint8_t spreadingFactor, Ptr< Packet > packet, uint32_t frequencyHz)
Add an event to the InterferenceHelper.
CollisionMatrix
Enumeration of types of collision matrices.
void CleanOldEvents()
Delete old events in this LoraInterferenceHelper.
void ClearAllEvents()
Delete all events in the LoraInterferenceHelper.
static CollisionMatrix collisionMatrix
Collision matrix type set by the constructor.
static std::vector< std::vector< double > > collisionSnirAloha
ALOHA collision matrix.
std::vector< std::vector< double > > m_collisionSnir
The matrix containing information about how packets survive interference.
void SetCollisionMatrix(enum CollisionMatrix collisionMatrix)
Set the collision matrix.
uint8_t IsDestroyedByInterference(Ptr< LoraInterferenceHelper::Event > event)
Determine whether the event was destroyed by interference or not.
void PrintEvents(std::ostream &stream)
Print the events that are saved in this helper in a human readable format.
std::list< Ptr< LoraInterferenceHelper::Event > > GetInterferers()
Get a list of the interferers currently registered at this InterferenceHelper.
std::list< Ptr< LoraInterferenceHelper::Event > > m_events
List of the events this LoraInterferenceHelper is keeping track of.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:267
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:454
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition simulator.cc:288
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
std::ostream & operator<<(std::ostream &os, const EndDeviceLoraPhy::State &state)
Overloaded operator to print the value of a EndDeviceLoraPhy::State.
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition lora-utils.cc:26
Every class exported by the ns3 library is enclosed in the ns3 namespace.