A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
correlated-shadowing-propagation-loss-model.cc
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: GPL-2.0-only
3 *
4 * Author: Davide Magrin <magrinda@dei.unipd.it>
5 */
6
8
9#include "ns3/double.h"
10#include "ns3/log.h"
11
12#include <cmath>
13
14namespace ns3
15{
16namespace lorawan
17{
18
19NS_LOG_COMPONENT_DEFINE("CorrelatedShadowingPropagationLossModel");
20
21NS_OBJECT_ENSURE_REGISTERED(CorrelatedShadowingPropagationLossModel);
22
23TypeId
25{
26 static TypeId tid =
27 TypeId("ns3::CorrelatedShwodingPropagationLossModel")
29 .SetGroupName("Lora")
31 .AddAttribute(
32 "CorrelationDistance",
33 "The distance at which the computed shadowing becomes"
34 "uncorrelated",
35 DoubleValue(110.0),
38 return tid;
39}
40
44
45double
48 Ptr<MobilityModel> b) const
49{
50 NS_LOG_FUNCTION(this << txPowerDbm << a << b);
51
52 /*
53 * Check whether the a MobilityModel is in a grid square that already has
54 * its shadowing map.
55 */
56 Vector position = a->GetPosition();
57
58 double x = position.x;
59 double y = position.y;
60
61 // Compute the coordinates of the grid square (i.e., round the raw position)
62 // (x > 0) - (x < 0) is the sign function
63 int xcoord =
64 ((x > 0) - (x < 0)) * ((std::fabs(x) + m_correlationDistance / 2) / m_correlationDistance);
65 int ycoord =
66 ((y > 0) - (y < 0)) * ((std::fabs(y) + m_correlationDistance / 2) / m_correlationDistance);
67
68 // Wrap coordinates up in a pair
69 std::pair<int, int> coordinates(xcoord, ycoord);
70
71 NS_LOG_DEBUG("x " << x << ", y " << y);
72 NS_LOG_DEBUG("xcoord " << xcoord << ", ycoord " << ycoord);
73
74 // Look for the computed coordinates in the shadowingGrid
75 std::map<std::pair<int, int>, Ptr<ShadowingMap>>::const_iterator it;
76
77 it = m_shadowingGrid.find(coordinates);
78
79 if (it == m_shadowingGrid.end()) // Did not find the coordinates
80 {
81 // If this shadowing grid was not found, create it
82 NS_LOG_DEBUG("Creating a new shadowing map to be used at coordinates "
83 << coordinates.first << " " << coordinates.second);
84
85 Ptr<ShadowingMap> shadowingMap =
87
88 m_shadowingGrid[coordinates] = shadowingMap;
89 }
90 else
91 {
92 NS_LOG_DEBUG("This square already has its shadowingMap!");
93 }
94
95 // Place the iterator on the coordinates
96 it = m_shadowingGrid.find(coordinates);
97
98 // Get b's position in a's ShadowingMap
99 CorrelatedShadowingPropagationLossModel::Position bPosition(b->GetPosition().x,
100 b->GetPosition().y);
101
102 // Use the map of the a MobilityModel to determine the value of shadowing
103 // that corresponds to the position of the MobilityModel b.
104 double loss = it->second->GetLoss(bPosition);
105
106 NS_LOG_INFO("Shadowing loss: " << loss);
107
108 return txPowerDbm - loss;
109}
110
111int64_t
113{
114 return 0;
115}
116
117/*********************************
118 * ShadowingMap implementation *
119 *********************************/
120
121// k^{-1} was computed offline
123 {1.27968707244633, -0.366414485833771, -0.0415206295795327, -0.366414485833771},
124 {-0.366414485833771, 1.27968707244633, -0.366414485833771, -0.0415206295795327},
125 {-0.0415206295795327, -0.366414485833771, 1.27968707244633, -0.366414485833771},
126 {-0.366414485833771, -0.0415206295795327, -0.366414485833771, 1.27968707244633}};
127
129 : m_correlationDistance(110)
130{
132
133 // The generation of new variables and positions along the grid is handled
134 // by the GetLoss function. Here, we only create the normal random variable.
136 m_shadowingValue->SetAttribute("Mean", DoubleValue(0.0));
137 m_shadowingValue->SetAttribute("Variance", DoubleValue(16.0));
138}
139
144
145double
148{
149 NS_LOG_FUNCTION(this << position.x << position.y);
150
151 // Verify whether this position is already in the shadowingMap. Since the
152 // Position implementation overloads the == operator, this comparison
153 // between doubles is ok and we can use std::map's find function.
154 std::map<CorrelatedShadowingPropagationLossModel::Position, double>::const_iterator it;
155 it = m_shadowingMap.find(position);
156
157 // If it's not found (i.e, if find returns the end of the map), we need to
158 // generate the value at the specified position.
159 if (it == m_shadowingMap.end())
160 {
161 // Get the coordinates of the position
162 double x = position.x;
163 double y = position.y;
164 int xcoord = ((x > 0) - (x < 0)) *
165 ((std::fabs(x) + m_correlationDistance / 2) / m_correlationDistance);
166 int ycoord = ((y > 0) - (y < 0)) *
167 ((std::fabs(y) + m_correlationDistance / 2) / m_correlationDistance);
168
169 // Verify whether there already are the 4 surrounding positions in the
170 // map
171 double xmin = xcoord * m_correlationDistance - m_correlationDistance / 2;
172 double xmax = xcoord * m_correlationDistance + m_correlationDistance / 2;
173 double ymin = ycoord * m_correlationDistance - m_correlationDistance / 2;
174 double ymax = ycoord * m_correlationDistance + m_correlationDistance / 2;
175
180
181 NS_LOG_DEBUG("Generating a new shadowing value in the following quadrant:");
182 NS_LOG_DEBUG("xmin " << xmin << ", xmax " << xmax << ", ymin " << ymin << ", ymax "
183 << ymax);
184
185 // Use the map's insert method to insert the coordinates of the 4
186 // surrounding positions (if they are already there, they won't be
187 // substituted thanks to the map's implementation).
188 // TODO: Avoid useless generation of ShadowingMap values. This can be
189 // done by performing some checks (and not leveraging the map
190 // implementation)
191 double q11 = m_shadowingValue->GetValue();
192 NS_LOG_DEBUG("Lower left corner: " << q11);
193 m_shadowingMap[lowerLeft] = q11;
194 double q12 = m_shadowingValue->GetValue();
195 NS_LOG_DEBUG("Upper left corner: " << q12);
196 m_shadowingMap[upperLeft] = q12;
197 double q21 = m_shadowingValue->GetValue();
198 NS_LOG_DEBUG("Lower right corner: " << q21);
199 m_shadowingMap[lowerRight] = q21;
200 double q22 = m_shadowingValue->GetValue();
201 NS_LOG_DEBUG("Upper right corner: " << q22);
202 m_shadowingMap[upperRight] = q22;
203
204 NS_LOG_DEBUG(q11 << " " << q12 << " " << q21 << " " << q22 << " ");
205
206 // The c matrix contains the positions of the 4 vertices
207 double c[2][4] = {{xmin, xmax, xmax, xmin}, {ymin, ymin, ymax, ymax}};
208
209 // For the following procedure, reference:
210 // S. Schlegel et al., "On the Interpolation of Data with Normally
211 // Distributed Uncertainty for Visualization", IEEE Transactions on
212 // Visualization and Computer Graphics, vol. 18, no. 12, Dec. 2012.
213
214 // Compute the phi coefficients
215 double phi1 = 0;
216 double phi2 = 0;
217 double phi3 = 0;
218 double phi4 = 0;
219
220 for (int j = 0; j < 4; j++)
221 {
222 double distance = sqrt((c[0][j] - x) * (c[0][j] - x) + (c[1][j] - y) * (c[1][j] - y));
223
224 NS_LOG_DEBUG("Distance: " << distance);
225
226 double k = std::exp(-distance / m_correlationDistance);
227 phi1 = phi1 + m_kInv[0][j] * k;
228 phi2 = phi2 + m_kInv[1][j] * k;
229 phi3 = phi3 + m_kInv[2][j] * k;
230 phi4 = phi4 + m_kInv[3][j] * k;
231 }
232
233 NS_LOG_DEBUG("Phi: " << phi1 << " " << phi2 << " " << phi3 << " " << phi4 << " ");
234
235 double shadowing = q11 * phi1 + q21 * phi2 + q22 * phi3 + q12 * phi4;
236
237 // Add the newly computed shadowing value to the shadowing map
238 m_shadowingMap[position] = shadowing;
239 NS_LOG_DEBUG("Created new shadowing map: " << shadowing);
240 }
241 else
242 {
243 NS_LOG_DEBUG("Shadowing map for this location already exists");
244 }
245
246 return m_shadowingMap[position];
247}
248
249/*****************************
250 * Position Implementation *
251 *****************************/
252
256
258{
259 this->x = x;
260 this->y = y;
261}
262
263/*
264 * Since Position holds two doubles, some tolerance must be taken into
265 * account when comparing for equality.
266 */
267bool
270{
271 double EPSILON = 0.1; // Arbitrary value for the tolerance, 10 cm.
272 return ((fabs(this->x - other.x) < EPSILON) && (fabs(this->y - other.y) < EPSILON));
273}
274
275/*
276 * In order to use Positions as keys in a map, we have to be able to order
277 * them correctly.
278 */
279bool
282{
283 if (this->x != other.x)
284 {
285 return this->x < other.x;
286 }
287 return this->y < other.y;
288}
289} // namespace lorawan
290} // namespace ns3
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
Models the propagation loss through a transmission medium.
Smart pointer class similar to boost::intrusive_ptr.
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
bool operator==(const Position &other) const
Equality comparison operator.
bool operator<(const Position &other) const
Less-then comparison operator.
double GetLoss(CorrelatedShadowingPropagationLossModel::Position position)
Get the loss for a certain position.
Ptr< NormalRandomVariable > m_shadowingValue
The normal random variable that is used to obtain shadowing values.
Propagation loss model for spatially correlated shadowing in a city.
double m_correlationDistance
The correlation distance for the ShadowingMap.
std::map< std::pair< int, int >, Ptr< ShadowingMap > > m_shadowingGrid
Map linking a square to a ShadowingMap.
double DoCalcRxPower(double txPowerDbm, Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
PropagationLossModel.
int64_t DoAssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
#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
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#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
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeDoubleChecker()
Definition double.h:82
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition double.h:32