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/mobility-model.h"
11
12namespace ns3
13{
14namespace lorawan
15{
16
17NS_LOG_COMPONENT_DEFINE("CorrelatedShadowingPropagationLossModel");
18
20
21TypeId
23{
24 static TypeId tid =
25 TypeId("ns3::CorrelatedShadowingPropagationLossModel")
27 .SetGroupName("Lora")
29 .AddAttribute(
30 "CorrelationDistance",
31 "The distance at which the computed shadowing becomes"
32 "uncorrelated",
33 DoubleValue(110.0),
36 return tid;
37}
38
42
43double
46 Ptr<MobilityModel> b) const
47{
48 NS_LOG_FUNCTION(this << txPowerDbm << a << b);
49
50 /*
51 * Check whether the a MobilityModel is in a grid square that already has
52 * its shadowing map.
53 */
54 Vector position = a->GetPosition();
55
56 double x = position.x;
57 double y = position.y;
58
59 // Compute the coordinates of the grid square (i.e., round the raw position)
60 // (x > 0) - (x < 0) is the sign function
61 int xcoord =
62 ((x > 0) - (x < 0)) * ((std::fabs(x) + m_correlationDistance / 2) / m_correlationDistance);
63 int ycoord =
64 ((y > 0) - (y < 0)) * ((std::fabs(y) + m_correlationDistance / 2) / m_correlationDistance);
65
66 // Wrap coordinates up in a pair
67 std::pair<int, int> coordinates(xcoord, ycoord);
68
69 NS_LOG_DEBUG("x " << x << ", y " << y);
70 NS_LOG_DEBUG("xcoord " << xcoord << ", ycoord " << ycoord);
71
72 // Look for the computed coordinates in the shadowingGrid
73 std::map<std::pair<int, int>, Ptr<ShadowingMap>>::const_iterator it;
74
75 it = m_shadowingGrid.find(coordinates);
76
77 if (it == m_shadowingGrid.end()) // Did not find the coordinates
78 {
79 // If this shadowing grid was not found, create it
80 NS_LOG_DEBUG("Creating a new shadowing map to be used at coordinates "
81 << coordinates.first << " " << coordinates.second);
82
83 Ptr<ShadowingMap> shadowingMap =
85
86 m_shadowingGrid[coordinates] = shadowingMap;
87 }
88 else
89 {
90 NS_LOG_DEBUG("This square already has its shadowingMap!");
91 }
92
93 // Place the iterator on the coordinates
94 it = m_shadowingGrid.find(coordinates);
95
96 // Get b's position in a's ShadowingMap
97 CorrelatedShadowingPropagationLossModel::Position bPosition(b->GetPosition().x,
98 b->GetPosition().y);
99
100 // Use the map of the a MobilityModel to determine the value of shadowing
101 // that corresponds to the position of the MobilityModel b.
102 double loss = it->second->GetLoss(bPosition);
103
104 NS_LOG_INFO("Shadowing loss: " << loss);
105
106 return txPowerDbm - loss;
107}
108
109int64_t
111{
112 return 0;
113}
114
115/*********************************
116 * ShadowingMap implementation *
117 *********************************/
118
119// k^{-1} was computed offline
121 {1.27968707244633, -0.366414485833771, -0.0415206295795327, -0.366414485833771},
122 {-0.366414485833771, 1.27968707244633, -0.366414485833771, -0.0415206295795327},
123 {-0.0415206295795327, -0.366414485833771, 1.27968707244633, -0.366414485833771},
124 {-0.366414485833771, -0.0415206295795327, -0.366414485833771, 1.27968707244633}};
125
128{
130
131 // The generation of new variables and positions along the grid is handled
132 // by the GetLoss function. Here, we only create the normal random variable.
134 m_shadowingValue->SetAttribute("Mean", DoubleValue(0.0));
135 m_shadowingValue->SetAttribute("Variance", DoubleValue(16.0));
136}
137
142
143double
146{
147 NS_LOG_FUNCTION(this << position.x << position.y);
148
149 // Verify whether this position is already in the shadowingMap. Since the
150 // Position implementation overloads the == operator, this comparison
151 // between doubles is ok and we can use std::map's find function.
152 std::map<CorrelatedShadowingPropagationLossModel::Position, double>::const_iterator it;
153 it = m_shadowingMap.find(position);
154
155 // If it's not found (i.e, if find returns the end of the map), we need to
156 // generate the value at the specified position.
157 if (it == m_shadowingMap.end())
158 {
159 // Get the coordinates of the position
160 double x = position.x;
161 double y = position.y;
162 int xcoord = ((x > 0) - (x < 0)) *
163 ((std::fabs(x) + m_correlationDistance / 2) / m_correlationDistance);
164 int ycoord = ((y > 0) - (y < 0)) *
165 ((std::fabs(y) + m_correlationDistance / 2) / m_correlationDistance);
166
167 // Verify whether there already are the 4 surrounding positions in the
168 // map
169 double xmin = xcoord * m_correlationDistance - m_correlationDistance / 2;
170 double xmax = xcoord * m_correlationDistance + m_correlationDistance / 2;
171 double ymin = ycoord * m_correlationDistance - m_correlationDistance / 2;
172 double ymax = ycoord * m_correlationDistance + m_correlationDistance / 2;
173
178
179 NS_LOG_DEBUG("Generating a new shadowing value in the following quadrant:");
180 NS_LOG_DEBUG("xmin " << xmin << ", xmax " << xmax << ", ymin " << ymin << ", ymax "
181 << ymax);
182
183 // Use the map's insert method to insert the coordinates of the 4
184 // surrounding positions (if they are already there, they won't be
185 // substituted thanks to the map's implementation).
186 // TODO: Avoid useless generation of ShadowingMap values. This can be
187 // done by performing some checks (and not leveraging the map
188 // implementation)
189 double q11 = m_shadowingValue->GetValue();
190 NS_LOG_DEBUG("Lower left corner: " << q11);
191 m_shadowingMap[lowerLeft] = q11;
192 double q12 = m_shadowingValue->GetValue();
193 NS_LOG_DEBUG("Upper left corner: " << q12);
194 m_shadowingMap[upperLeft] = q12;
195 double q21 = m_shadowingValue->GetValue();
196 NS_LOG_DEBUG("Lower right corner: " << q21);
197 m_shadowingMap[lowerRight] = q21;
198 double q22 = m_shadowingValue->GetValue();
199 NS_LOG_DEBUG("Upper right corner: " << q22);
200 m_shadowingMap[upperRight] = q22;
201
202 NS_LOG_DEBUG(q11 << " " << q12 << " " << q21 << " " << q22 << " ");
203
204 // The c matrix contains the positions of the 4 vertices
205 double c[2][4] = {{xmin, xmax, xmax, xmin}, {ymin, ymin, ymax, ymax}};
206
207 // For the following procedure, reference:
208 // S. Schlegel et al., "On the Interpolation of Data with Normally
209 // Distributed Uncertainty for Visualization", IEEE Transactions on
210 // Visualization and Computer Graphics, vol. 18, no. 12, Dec. 2012.
211
212 // Compute the phi coefficients
213 double phi1 = 0;
214 double phi2 = 0;
215 double phi3 = 0;
216 double phi4 = 0;
217
218 for (int j = 0; j < 4; j++)
219 {
220 double distance = sqrt((c[0][j] - x) * (c[0][j] - x) + (c[1][j] - y) * (c[1][j] - y));
221
222 NS_LOG_DEBUG("Distance: " << distance);
223
224 double k = std::exp(-distance / m_correlationDistance);
225 phi1 = phi1 + m_kInv[0][j] * k;
226 phi2 = phi2 + m_kInv[1][j] * k;
227 phi3 = phi3 + m_kInv[2][j] * k;
228 phi4 = phi4 + m_kInv[3][j] * k;
229 }
230
231 NS_LOG_DEBUG("Phi: " << phi1 << " " << phi2 << " " << phi3 << " " << phi4 << " ");
232
233 double shadowing = q11 * phi1 + q21 * phi2 + q22 * phi3 + q12 * phi4;
234
235 // Add the newly computed shadowing value to the shadowing map
236 m_shadowingMap[position] = shadowing;
237 NS_LOG_DEBUG("Created new shadowing map: " << shadowing);
238 }
239 else
240 {
241 NS_LOG_DEBUG("Shadowing map for this location already exists");
242 }
243
244 return m_shadowingMap[position];
245}
246
247/*****************************
248 * Position Implementation *
249 *****************************/
250
254
256{
257 this->x = x;
258 this->y = y;
259}
260
261/*
262 * Since Position holds two doubles, some tolerance must be taken into
263 * account when comparing for equality.
264 */
265bool
268{
269 double EPSILON = 0.1; // Arbitrary value for the tolerance, 10 cm.
270 return ((fabs(this->x - other.x) < EPSILON) && (fabs(this->y - other.y) < EPSILON));
271}
272
273/*
274 * In order to use Positions as keys in a map, we have to be able to order
275 * them correctly.
276 */
277bool
280{
281 if (this->x != other.x)
282 {
283 return this->x < other.x;
284 }
285 return this->y < other.y;
286}
287
288} // namespace lorawan
289} // namespace ns3
cairo_uint64_t x
_cairo_uint_96by64_32x64_divrem:
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
a unique identifier for an interface.
Definition type-id.h:50
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
bool operator==(const Position &other) const
Equality comparison operator.
bool operator<(const Position &other) const
Less-then comparison operator.
double m_correlationDistance
The distance after which two samples are to be considered almost uncorrelated.
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.
std::map< CorrelatedShadowingPropagationLossModel::Position, double > m_shadowingMap
For each Position, this map gives a corresponding loss.
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: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 > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
#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:454
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