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 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation;
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 *
15 * Author: Davide Magrin <magrinda@dei.unipd.it>
16 */
17
19
20#include "ns3/double.h"
21#include "ns3/log.h"
22
23#include <cmath>
24
25namespace ns3
26{
27namespace lorawan
28{
29
30NS_LOG_COMPONENT_DEFINE("CorrelatedShadowingPropagationLossModel");
31
32NS_OBJECT_ENSURE_REGISTERED(CorrelatedShadowingPropagationLossModel);
33
34TypeId
36{
37 static TypeId tid =
38 TypeId("ns3::CorrelatedShwodingPropagationLossModel")
40 .SetGroupName("Lora")
42 .AddAttribute(
43 "CorrelationDistance",
44 "The distance at which the computed shadowing becomes"
45 "uncorrelated",
46 DoubleValue(110.0),
48 MakeDoubleChecker<double>());
49 return tid;
50}
51
53{
54}
55
56double
59 Ptr<MobilityModel> b) const
60{
61 NS_LOG_FUNCTION(this << txPowerDbm << a << b);
62
63 /*
64 * Check whether the a MobilityModel is in a grid square that already has
65 * its shadowing map.
66 */
67 Vector position = a->GetPosition();
68
69 double x = position.x;
70 double y = position.y;
71
72 // Compute the coordinates of the grid square (i.e., round the raw position)
73 // (x > 0) - (x < 0) is the sign function
74 int xcoord =
75 ((x > 0) - (x < 0)) * ((std::fabs(x) + m_correlationDistance / 2) / m_correlationDistance);
76 int ycoord =
77 ((y > 0) - (y < 0)) * ((std::fabs(y) + m_correlationDistance / 2) / m_correlationDistance);
78
79 // Wrap coordinates up in a pair
80 std::pair<int, int> coordinates(xcoord, ycoord);
81
82 NS_LOG_DEBUG("x " << x << ", y " << y);
83 NS_LOG_DEBUG("xcoord " << xcoord << ", ycoord " << ycoord);
84
85 // Look for the computed coordinates in the shadowingGrid
86 std::map<std::pair<int, int>, Ptr<ShadowingMap>>::const_iterator it;
87
88 it = m_shadowingGrid.find(coordinates);
89
90 if (it == m_shadowingGrid.end()) // Did not find the coordinates
91 {
92 // If this shadowing grid was not found, create it
93 NS_LOG_DEBUG("Creating a new shadowing map to be used at coordinates "
94 << coordinates.first << " " << coordinates.second);
95
96 Ptr<ShadowingMap> shadowingMap =
97 Create<CorrelatedShadowingPropagationLossModel::ShadowingMap>();
98
99 m_shadowingGrid[coordinates] = shadowingMap;
100 }
101 else
102 {
103 NS_LOG_DEBUG("This square already has its shadowingMap!");
104 }
105
106 // Place the iterator on the coordinates
107 it = m_shadowingGrid.find(coordinates);
108
109 // Get b's position in a's ShadowingMap
110 CorrelatedShadowingPropagationLossModel::Position bPosition(b->GetPosition().x,
111 b->GetPosition().y);
112
113 // Use the map of the a MobilityModel to determine the value of shadowing
114 // that corresponds to the position of the MobilityModel b.
115 double loss = it->second->GetLoss(bPosition);
116
117 NS_LOG_INFO("Shadowing loss: " << loss);
118
119 return txPowerDbm - loss;
120}
121
122int64_t
124{
125 return 0;
126}
127
128/*********************************
129 * ShadowingMap implementation *
130 *********************************/
131
132// k^{-1} was computed offline
134 {1.27968707244633, -0.366414485833771, -0.0415206295795327, -0.366414485833771},
135 {-0.366414485833771, 1.27968707244633, -0.366414485833771, -0.0415206295795327},
136 {-0.0415206295795327, -0.366414485833771, 1.27968707244633, -0.366414485833771},
137 {-0.366414485833771, -0.0415206295795327, -0.366414485833771, 1.27968707244633}};
138
140 : m_correlationDistance(110)
141{
143
144 // The generation of new variables and positions along the grid is handled
145 // by the GetLoss function. Here, we only create the normal random variable.
146 m_shadowingValue = CreateObject<NormalRandomVariable>();
147 m_shadowingValue->SetAttribute("Mean", DoubleValue(0.0));
148 m_shadowingValue->SetAttribute("Variance", DoubleValue(16.0));
149}
150
152{
154}
155
156double
159{
160 NS_LOG_FUNCTION(this << position.x << position.y);
161
162 // Verify whether this position is already in the shadowingMap. Since the
163 // Position implementation overloads the == operator, this comparison
164 // between doubles is ok and we can use std::map's find function.
165 std::map<CorrelatedShadowingPropagationLossModel::Position, double>::const_iterator it;
166 it = m_shadowingMap.find(position);
167
168 // If it's not found (i.e, if find returns the end of the map), we need to
169 // generate the value at the specified position.
170 if (it == m_shadowingMap.end())
171 {
172 // Get the coordinates of the position
173 double x = position.x;
174 double y = position.y;
175 int xcoord = ((x > 0) - (x < 0)) *
176 ((std::fabs(x) + m_correlationDistance / 2) / m_correlationDistance);
177 int ycoord = ((y > 0) - (y < 0)) *
178 ((std::fabs(y) + m_correlationDistance / 2) / m_correlationDistance);
179
180 // Verify whether there already are the 4 surrounding positions in the
181 // map
182 double xmin = xcoord * m_correlationDistance - m_correlationDistance / 2;
183 double xmax = xcoord * m_correlationDistance + m_correlationDistance / 2;
184 double ymin = ycoord * m_correlationDistance - m_correlationDistance / 2;
185 double ymax = ycoord * m_correlationDistance + m_correlationDistance / 2;
186
191
192 NS_LOG_DEBUG("Generating a new shadowing value in the following quadrant:");
193 NS_LOG_DEBUG("xmin " << xmin << ", xmax " << xmax << ", ymin " << ymin << ", ymax "
194 << ymax);
195
196 // Use the map's insert method to insert the coordinates of the 4
197 // surrounding positions (if they are already there, they won't be
198 // substituted thanks to the map's implementation).
199 // TODO: Avoid useless generation of ShadowingMap values. This can be
200 // done by performing some checks (and not leveraging the map
201 // implementation)
202 double q11 = m_shadowingValue->GetValue();
203 NS_LOG_DEBUG("Lower left corner: " << q11);
204 m_shadowingMap[lowerLeft] = q11;
205 double q12 = m_shadowingValue->GetValue();
206 NS_LOG_DEBUG("Upper left corner: " << q12);
207 m_shadowingMap[upperLeft] = q12;
208 double q21 = m_shadowingValue->GetValue();
209 NS_LOG_DEBUG("Lower right corner: " << q21);
210 m_shadowingMap[lowerRight] = q21;
211 double q22 = m_shadowingValue->GetValue();
212 NS_LOG_DEBUG("Upper right corner: " << q22);
213 m_shadowingMap[upperRight] = q22;
214
215 NS_LOG_DEBUG(q11 << " " << q12 << " " << q21 << " " << q22 << " ");
216
217 // The c matrix contains the positions of the 4 vertices
218 double c[2][4] = {{xmin, xmax, xmax, xmin}, {ymin, ymin, ymax, ymax}};
219
220 // For the following procedure, reference:
221 // S. Schlegel et al., "On the Interpolation of Data with Normally
222 // Distributed Uncertainty for Visualization", IEEE Transactions on
223 // Visualization and Computer Graphics, vol. 18, no. 12, Dec. 2012.
224
225 // Compute the phi coefficients
226 double phi1 = 0;
227 double phi2 = 0;
228 double phi3 = 0;
229 double phi4 = 0;
230
231 for (int j = 0; j < 4; j++)
232 {
233 double distance = sqrt((c[0][j] - x) * (c[0][j] - x) + (c[1][j] - y) * (c[1][j] - y));
234
235 NS_LOG_DEBUG("Distance: " << distance);
236
237 double k = std::exp(-distance / m_correlationDistance);
238 phi1 = phi1 + m_kInv[0][j] * k;
239 phi2 = phi2 + m_kInv[1][j] * k;
240 phi3 = phi3 + m_kInv[2][j] * k;
241 phi4 = phi4 + m_kInv[3][j] * k;
242 }
243
244 NS_LOG_DEBUG("Phi: " << phi1 << " " << phi2 << " " << phi3 << " " << phi4 << " ");
245
246 double shadowing = q11 * phi1 + q21 * phi2 + q22 * phi3 + q12 * phi4;
247
248 // Add the newly computed shadowing value to the shadowing map
249 m_shadowingMap[position] = shadowing;
250 NS_LOG_DEBUG("Created new shadowing map: " << shadowing);
251 }
252 else
253 {
254 NS_LOG_DEBUG("Shadowing map for this location already exists");
255 }
256
257 return m_shadowingMap[position];
258}
259
260/*****************************
261 * Position Implementation *
262 *****************************/
263
265{
266}
267
269{
270 this->x = x;
271 this->y = y;
272}
273
274/*
275 * Since Position holds two doubles, some tolerance must be taken into
276 * account when comparing for equality.
277 */
278bool
281{
282 double EPSILON = 0.1; // Arbitrary value for the tolerance, 10 cm.
283 return ((fabs(this->x - other.x) < EPSILON) && (fabs(this->y - other.y) < EPSILON));
284}
285
286/*
287 * In order to use Positions as keys in a map, we have to be able to order
288 * them correctly.
289 */
290bool
293{
294 if (this->x != other.x)
295 {
296 return this->x < other.x;
297 }
298 return this->y < other.y;
299}
300} // namespace lorawan
301} // namespace ns3
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Models the propagation loss through a transmission medium.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
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:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43