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/enum.h"
14#include "ns3/log.h"
15
16#include <limits>
17
18namespace ns3
19{
20namespace lorawan
21{
22
23NS_LOG_COMPONENT_DEFINE("LoraInterferenceHelper");
24
25/***************************************
26 * LoraInterferenceHelper::Event *
27 ***************************************/
28
29// Event Constructor
31 double rxPowerdBm,
32 uint8_t spreadingFactor,
33 Ptr<Packet> packet,
34 uint32_t frequencyHz)
35 : m_startTime(Now()),
36 m_endTime(m_startTime + duration),
37 m_sf(spreadingFactor),
38 m_rxPowerdBm(rxPowerdBm),
39 m_packet(packet),
40 m_frequencyHz(frequencyHz)
41{
42 // NS_LOG_FUNCTION_NOARGS ();
43}
44
45// Event Destructor
47{
48 // NS_LOG_FUNCTION_NOARGS ();
49}
50
51// Getters
52Time
57
58Time
63
64Time
69
70double
75
76uint8_t
81
87
93
94void
95LoraInterferenceHelper::Event::Print(std::ostream& stream) const
96{
97 stream << "(" << m_startTime.As(Time::S) << " - " << m_endTime.As(Time::S) << "), SF"
98 << unsigned(m_sf) << ", " << m_rxPowerdBm << " dBm, " << m_frequencyHz << " Hz";
99}
100
101std::ostream&
102operator<<(std::ostream& os, const LoraInterferenceHelper::Event& event)
103{
104 event.Print(os);
105
106 return os;
107}
108
109/****************************
110 * LoraInterferenceHelper *
111 ****************************/
112// This collision matrix can be used for comparisons with the performance of Aloha
113// systems, where collisions imply the loss of both packets.
114double inf = std::numeric_limits<double>::max();
115std::vector<std::vector<double>> LoraInterferenceHelper::collisionSnirAloha = {
116 // 7 8 9 10 11 12
117 {inf, -inf, -inf, -inf, -inf, -inf}, // SF7
118 {-inf, inf, -inf, -inf, -inf, -inf}, // SF8
119 {-inf, -inf, inf, -inf, -inf, -inf}, // SF9
120 {-inf, -inf, -inf, inf, -inf, -inf}, // SF10
121 {-inf, -inf, -inf, -inf, inf, -inf}, // SF11
122 {-inf, -inf, -inf, -inf, -inf, inf} // SF12
123};
124
125// LoRa Collision Matrix (Goursaud)
126// Values are inverted w.r.t. the paper since here we interpret this as an
127// _isolation_ matrix instead of a cochannel _rejection_ matrix like in
128// Goursaud's paper.
129std::vector<std::vector<double>> LoraInterferenceHelper::collisionSnirGoursaud = {
130 // SF7 SF8 SF9 SF10 SF11 SF12
131 {6, -16, -18, -19, -19, -20}, // SF7
132 {-24, 6, -20, -22, -22, -22}, // SF8
133 {-27, -27, 6, -23, -25, -25}, // SF9
134 {-30, -30, -30, 6, -26, -28}, // SF10
135 {-33, -33, -33, -33, 6, -29}, // SF11
136 {-36, -36, -36, -36, -36, 6} // SF12
137};
138
141
143
144void
160
161TypeId
163{
164 static TypeId tid =
165 TypeId("ns3::LoraInterferenceHelper").SetParent<Object>().SetGroupName("lorawan");
166
167 return tid;
168}
169
177
182
184
187 double rxPower,
188 uint8_t spreadingFactor,
189 Ptr<Packet> packet,
190 uint32_t frequencyHz)
191{
192 NS_LOG_FUNCTION(this << duration.As(Time::MS) << rxPower << unsigned(spreadingFactor) << packet
193 << frequencyHz);
194
195 // Create an event based on the parameters
198 rxPower,
199 spreadingFactor,
200 packet,
201 frequencyHz);
202
203 // Add the event to the list
204 m_events.push_back(event);
205
206 // Clean the event list
207 if (m_events.size() > 100)
208 {
210 }
211
212 return event;
213}
214
215void
217{
218 NS_LOG_FUNCTION(this);
219
220 // Cycle the events, and clean up if an event is old.
221 for (auto it = m_events.begin(); it != m_events.end();)
222 {
223 if ((*it)->GetEndTime() + oldEventThreshold < Now())
224 {
225 it = m_events.erase(it);
226 }
227 else
228 {
229 it++;
230 }
231 }
232}
233
234std::list<Ptr<LoraInterferenceHelper::Event>>
239
240void
242{
244
245 stream << "Currently registered events:" << std::endl;
246
247 for (auto it = m_events.begin(); it != m_events.end(); it++)
248 {
249 (*it)->Print(stream);
250 stream << std::endl;
251 }
252}
253
254uint8_t
256{
257 NS_LOG_FUNCTION(this << event);
258
259 NS_LOG_INFO("Current number of events in LoraInterferenceHelper: " << m_events.size());
260
261 // We want to see the interference affecting this event: cycle through events
262 // that overlap with this one and see whether it survives the interference or
263 // not.
264
265 // Gather information about the event
266 double rxPowerDbm = event->GetRxPowerdBm();
267 uint8_t sf = event->GetSpreadingFactor();
268 uint32_t frequencyHz = event->GetFrequency();
269
270 // Handy information about the time frame when the packet was received
271 Time now = Now();
272 Time duration = event->GetDuration();
273 Time packetStartTime = now - duration;
274
275 // Get the list of interfering events
276 std::list<Ptr<LoraInterferenceHelper::Event>>::iterator it;
277
278 // Energy for interferers of various SFs
279 std::vector<double> cumulativeInterferenceEnergy(6, 0);
280
281 // Cycle over the events
282 for (it = m_events.begin(); it != m_events.end();)
283 {
284 // Pointer to the current interferer
285 Ptr<LoraInterferenceHelper::Event> interferer = *it;
286
287 // Only consider the current event if the channel is the same: we
288 // assume there's no interchannel interference. Also skip the current
289 // event if it's the same that we want to analyze.
290 if (!(interferer->GetFrequency() == frequencyHz) || interferer == event)
291 {
292 NS_LOG_DEBUG("Different channel or same event");
293 it++;
294 continue; // Continues from the first line inside the for cycle
295 }
296
297 NS_LOG_DEBUG("Interferer on same channel");
298
299 // Gather information about this interferer
300 uint8_t interfererSf = interferer->GetSpreadingFactor();
301 double interfererPower = interferer->GetRxPowerdBm();
302 Time interfererStartTime = interferer->GetStartTime();
303 Time interfererEndTime = interferer->GetEndTime();
304
305 NS_LOG_INFO("Found an interferer: sf = " << unsigned(interfererSf)
306 << ", power = " << interfererPower
307 << ", start time = " << interfererStartTime
308 << ", end time = " << interfererEndTime);
309
310 // Compute the fraction of time the two events are overlapping
311 Time overlap = GetOverlapTime(event, interferer);
312
313 NS_LOG_DEBUG("The two events overlap for " << overlap.As(Time::S));
314
315 double interfererPowerW = DbmToW(interfererPower);
316 // Energy [J] = Time [s] * Power [W]
317 double interferenceEnergy = overlap.GetSeconds() * interfererPowerW;
318 cumulativeInterferenceEnergy.at(unsigned(interfererSf) - 7) += interferenceEnergy;
319 NS_LOG_DEBUG("Interferer power in W: " << interfererPowerW);
320 NS_LOG_DEBUG("Interference energy: " << interferenceEnergy);
321 it++;
322 }
323
324 // For each spreading factor, check if there was destructive interference
325 for (auto currentSf = uint8_t(7); currentSf <= uint8_t(12); currentSf++)
326 {
327 NS_LOG_DEBUG("Cumulative Interference Energy: "
328 << cumulativeInterferenceEnergy.at(unsigned(currentSf) - 7));
329
330 // Use the computed cumulativeInterferenceEnergy to determine whether the
331 // interference with this spreading factor destroys the packet
332 double signalPowerW = DbmToW(rxPowerDbm);
333 double signalEnergy = duration.GetSeconds() * signalPowerW;
334 NS_LOG_DEBUG("Signal power in W: " << signalPowerW);
335 NS_LOG_DEBUG("Signal energy: " << signalEnergy);
336
337 // Check whether the packet survives the interference of this spreading factor
338 double snirIsolation = m_collisionSnir[unsigned(sf) - 7][unsigned(currentSf) - 7];
339 NS_LOG_DEBUG("The needed isolation to survive is " << snirIsolation << " dB");
340 double snir =
341 10 * log10(signalEnergy / cumulativeInterferenceEnergy.at(unsigned(currentSf) - 7));
342 NS_LOG_DEBUG("The current SNIR is " << snir << " dB");
343
344 if (snir >= snirIsolation)
345 {
346 // Move on and check the rest of the interferers
347 NS_LOG_DEBUG("Packet survived interference with SF " << currentSf);
348 }
349 else
350 {
351 NS_LOG_DEBUG("Packet destroyed by interference with SF" << unsigned(currentSf));
352
353 return currentSf;
354 }
355 }
356 // If we get to here, it means that the packet survived all interference
357 NS_LOG_DEBUG("Packet survived all interference");
358
359 // Since the packet was not destroyed, we return 0.
360 return uint8_t(0);
361}
362
363void
370
371Time
374{
376
377 // Create the value we will return later
378 Time overlap;
379
380 // Get handy values
381 Time s1 = event1->GetStartTime(); // Start times
382 Time s2 = event2->GetStartTime();
383 Time e1 = event1->GetEndTime(); // End times
384 Time e2 = event2->GetEndTime();
385
386 // Non-overlapping events
387 if (e1 <= s2 || e2 <= s1)
388 {
389 overlap = Time(0);
390 }
391 // event1 before event2
392 else if (s1 < s2)
393 {
394 if (e2 < e1)
395 {
396 overlap = e2 - s2;
397 }
398 else
399 {
400 overlap = e1 - s2;
401 }
402 }
403 // event2 before event1 or they start at the same time (s1 = s2)
404 else
405 {
406 if (e1 < e2)
407 {
408 overlap = e1 - s1;
409 }
410 else
411 {
412 overlap = e2 - s1;
413 }
414 }
415
416 return overlap;
417}
418} // namespace lorawan
419} // namespace ns3
420
421/*
422 ----------------------------------------------------------------------------
423
424 // Event1 starts before Event2
425 if (s1 < s2)
426 {
427 // Non-overlapping events
428 if (e1 < s2)
429 {
430 overlap = Seconds (0);
431 }
432 // event1 contains event2
433 else if (e1 >= e2)
434 {
435 overlap = e2 - s2;
436 }
437 // Partially overlapping events
438 else
439 {
440 overlap = e1 - s2;
441 }
442 }
443 // Event2 starts before Event1
444 else
445 {
446 // Non-overlapping events
447 if (e2 < s1)
448 {
449 overlap = Seconds (0);
450 }
451 // event2 contains event1
452 else if (e2 >= e1)
453 {
454 overlap = e1 - s1;
455 }
456 // Partially overlapping events
457 else
458 {
459 overlap = e2 - s1;
460 }
461 }
462 return overlap;
463 }
464 }
465 }
466*/
A base class which provides memory management and object aggregation.
Definition object.h:78
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:66
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:403
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
@ MS
millisecond
Definition nstime.h:106
@ S
second
Definition nstime.h:105
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
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.
static TypeId GetTypeId()
Register this type.
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:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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:264
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition simulator.cc:294
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition lora-utils.cc:26
std::ostream & operator<<(std::ostream &os, const EndDeviceStatus &status)
Every class exported by the ns3 library is enclosed in the ns3 namespace.