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