A Discrete-Event Network Simulator
API
buildings-shadowing-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Marco Miozzo <marco.miozzo@cttc.es>
18  * Nicola Baldo <nbaldo@cttc.es>
19  */
20 
22 
23 #include <ns3/building.h>
24 #include <ns3/buildings-helper.h>
25 #include <ns3/constant-position-mobility-model.h>
26 #include <ns3/double.h>
27 #include <ns3/enum.h>
28 #include <ns3/hybrid-buildings-propagation-loss-model.h>
29 #include <ns3/log.h>
30 #include <ns3/mobility-building-info.h>
31 #include <ns3/mobility-model.h>
32 #include <ns3/ptr.h>
33 #include <ns3/simulator.h>
34 #include <ns3/string.h>
35 
36 using namespace ns3;
37 
38 NS_LOG_COMPONENT_DEFINE("BuildingsShadowingTest");
39 
40 /*
41  * Test 1.1 Shadowing compound test
42  *
43  * This TestSuite tests the shadowing model of BuildingPathlossModel
44  * by reproducing several communication scenarios
45  */
46 
48  : TestSuite("buildings-shadowing-test", SYSTEM)
49 {
50  LogComponentEnable("BuildingsShadowingTest", LOG_LEVEL_ALL);
51 
52  // Test #1 Outdoor Model
53  AddTestCase(new BuildingsShadowingTestCase(1, 2, 148.86, 7.0, "Outdoor Shadowing"),
54  TestCase::QUICK);
55 
56  // Test #2 Indoor model
57  AddTestCase(new BuildingsShadowingTestCase(5, 6, 88.5724, 8.0, "Indoor Shadowing"),
58  TestCase::QUICK);
59 
60  // Test #3 Indoor -> Outdoor
61  AddTestCase(new BuildingsShadowingTestCase(9, 10, 85.0012, 8.6, "Indoor -> Outdoor Shadowing"),
62  TestCase::QUICK);
63 }
64 
67 
68 /*
69  * TestCase
70  */
71 
73  uint16_t m2,
74  double refValue,
75  double sigmaRef,
76  std::string name)
77  : TestCase("SHADOWING calculation: " + name),
78  m_mobilityModelIndex1(m1),
79  m_mobilityModelIndex2(m2),
80  m_lossRef(refValue),
81  m_sigmaRef(sigmaRef)
82 {
83 }
84 
86 {
87 }
88 
89 void
91 {
92  NS_LOG_FUNCTION(this);
93 
94  // the building basically occupies the negative x plane, so any node
95  // in this area will fall in the building
96  Ptr<Building> building1 = CreateObject<Building>();
97  building1->SetBoundaries(Box(-3000, -1, -4000, 4000.0, 0.0, 12));
98  building1->SetBuildingType(Building::Residential);
99  building1->SetExtWallsType(Building::ConcreteWithWindows);
100  building1->SetNFloors(3);
101 
102  Ptr<HybridBuildingsPropagationLossModel> propagationLossModel =
103  CreateObject<HybridBuildingsPropagationLossModel>();
104 
105  std::vector<double> loss;
106  double sum = 0.0;
107  double sumSquared = 0.0;
108  int samples = 1000;
109  for (int i = 0; i < samples; i++)
110  {
113  double shadowingLoss = propagationLossModel->DoCalcRxPower(0.0, mma, mmb) + m_lossRef;
114  double shadowingLoss2 = propagationLossModel->DoCalcRxPower(0.0, mma, mmb) + m_lossRef;
115  NS_TEST_ASSERT_MSG_EQ_TOL(shadowingLoss,
116  shadowingLoss2,
117  0.001,
118  "Shadowing is not constant for the same mobility model pair!");
119  loss.push_back(shadowingLoss);
120  sum += shadowingLoss;
121  sumSquared += (shadowingLoss * shadowingLoss);
122  }
123  double sampleMean = sum / samples;
124  double sampleVariance = (sumSquared - (sum * sum / samples)) / (samples - 1);
125  double sampleStd = std::sqrt(sampleVariance);
126 
127  // test whether the sample mean falls in the 99% confidence interval
128  const double zn995 = 2.575829303549; // 99.5 quantile of the normal distribution
129  double ci = (zn995 * sampleStd) / std::sqrt(samples);
130  NS_LOG_INFO("SampleMean from simulation " << sampleMean << ", sampleStd " << sampleStd
131  << ", reference value " << m_sigmaRef << ", CI(99%) "
132  << ci);
133  NS_TEST_ASSERT_MSG_EQ_TOL(std::fabs(sampleMean), 0.0, ci, "Wrong shadowing distribution !");
134 
135  // test whether the sample variance falls in the 99% confidence interval
136  // since the shadowing is gaussian, its sample variance follows the
137  // chi2 distribution with samples-1 degrees of freedom
138  double chi2 = (samples - 1) * sampleVariance / (m_sigmaRef * m_sigmaRef);
139  const double zchi2_005 = 887.621135217515; // 0.5% quantile of the chi2 distribution
140  const double zchi2_995 = 1117.89045267865; // 99.5% quantile of the chi2 distribution
141  NS_TEST_ASSERT_MSG_GT(chi2, zchi2_005, "sample variance lesser than expected");
142  NS_TEST_ASSERT_MSG_LT(chi2, zchi2_995, "sample variance greater than expected");
143 
144  Simulator::Destroy();
145 }
146 
149 {
150  /*
151  * The purpose of this method is to defer the creation of the
152  * MobilityModel instances to when DoRun() is called. In a previous
153  * version, MobilityModel instances where created directly in the
154  * constructor of the test suite, which caused subtle bugs due to
155  * "static initialization order fiasco". An example of such a subtle
156  * bug is that logging via NS_LOG failed for some modules.
157  *
158  */
159 
160  double hm = 1;
161  double hb = 30;
162  double henbHeight = 10.0;
163 
165 
166  switch (index)
167  {
168  case 1:
169  mm = CreateObject<ConstantPositionMobilityModel>();
170  mm->SetPosition(Vector(0.0, 0.0, hb));
171  break;
172 
173  case 2:
174  mm = CreateObject<ConstantPositionMobilityModel>();
175  mm->SetPosition(Vector(2000, 0.0, hm));
176  break;
177 
178  case 3:
179  mm = CreateObject<ConstantPositionMobilityModel>();
180  mm->SetPosition(Vector(100, 0.0, hm));
181  break;
182 
183  case 4:
184  mm = CreateObject<ConstantPositionMobilityModel>();
185  mm->SetPosition(Vector(900, 0.0, hm));
186  break;
187 
188  case 5:
189  mm = CreateObject<ConstantPositionMobilityModel>();
190  mm->SetPosition(Vector(-5, 0.0, hm));
191  break;
192 
193  case 6:
194  mm = CreateObject<ConstantPositionMobilityModel>();
195  mm->SetPosition(Vector(-5, 30, henbHeight));
196  break;
197 
198  case 7:
199  mm = CreateObject<ConstantPositionMobilityModel>();
200  mm->SetPosition(Vector(-2000, 0.0, hm));
201  break;
202 
203  case 8:
204  mm = CreateObject<ConstantPositionMobilityModel>();
205  mm->SetPosition(Vector(-100, 0.0, hm));
206  break;
207 
208  case 9:
209  mm = CreateObject<ConstantPositionMobilityModel>();
210  mm->SetPosition(Vector(0, 0.0, hm));
211  break;
212 
213  case 10:
214  mm = CreateObject<ConstantPositionMobilityModel>();
215  mm->SetPosition(Vector(-100, 0.0, henbHeight));
216  break;
217 
218  case 11:
219  mm = CreateObject<ConstantPositionMobilityModel>();
220  mm->SetPosition(Vector(-500, 0.0, henbHeight));
221  break;
222 
223  default:
224  mm = nullptr;
225  break;
226  }
227  Ptr<MobilityBuildingInfo> buildingInfo = CreateObject<MobilityBuildingInfo>();
228  mm->AggregateObject(buildingInfo); // operation usually done by BuildingsHelper::Install
229  buildingInfo->MakeConsistent(mm);
230  return mm;
231 }
static BuildingsShadowingTestSuite buildingsShadowingTestSuite
Static variable for test initialization.
uint16_t m_mobilityModelIndex2
Second MobilityModel Index.
Ptr< MobilityModel > CreateMobilityModel(uint16_t index)
Create a mobility model based on its index.
uint16_t m_mobilityModelIndex1
First MobilityModel Index.
double m_lossRef
pathloss value (without shadowing)
void DoRun() override
Implementation to actually run this TestCase.
BuildingsShadowingTestCase(uint16_t m1, uint16_t m2, double refValue, double sigmaRef, std::string name)
Constructor.
double m_sigmaRef
pathloss standard deviation value reference value
a 3d box
Definition: box.h:35
void SetPosition(const Vector &position)
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:259
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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_TEST_ASSERT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report and abort if not.
Definition: test.h:709
#define NS_TEST_ASSERT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report and abort if not.
Definition: test.h:874
#define NS_TEST_ASSERT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
Definition: test.h:337
const double m1
First component modulus, 232 - 209.
Definition: rng-stream.cc:60
const double m2
Second component modulus, 232 - 22853.
Definition: rng-stream.cc:63
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:302
@ LOG_LEVEL_ALL
Print everything.
Definition: log.h:116