A Discrete-Event Network Simulator
API
channel-condition-model-test-suite.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 SIGNET Lab, Department of Information Engineering,
3  * University of Padova
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */
18 
19 #include "ns3/abort.h"
20 #include "ns3/channel-condition-model.h"
21 #include "ns3/config.h"
22 #include "ns3/constant-position-mobility-model.h"
23 #include "ns3/double.h"
24 #include "ns3/log.h"
25 #include "ns3/node-container.h"
26 #include "ns3/simulator.h"
27 #include "ns3/test.h"
28 
29 using namespace ns3;
30 
31 NS_LOG_COMPONENT_DEFINE("ChannelConditionModelsTest");
32 
42 {
43  public:
48 
53 
54  private:
58  void DoRun() override;
59 
67  void EvaluateChannelCondition(Ptr<MobilityModel> a, Ptr<MobilityModel> b);
68 
72  struct TestVector
73  {
74  Vector m_positionA;
75  Vector m_positionB;
76  double m_pLos;
78  };
79 
82  uint64_t m_numLos;
83  double m_tolerance;
84 };
85 
87  : TestCase("Test case for the child classes of ThreeGppChannelConditionModel"),
88  m_testVectors(),
89  m_tolerance(2e-3)
90 {
91 }
92 
94 {
95 }
96 
97 void
100 {
102  if (cond->GetLosCondition() == ChannelCondition::LosConditionValue::LOS)
103  {
104  m_numLos++;
105  }
106 }
107 
108 void
110 {
111  // create the test vector
112  TestVector testVector;
113 
114  // tests for the RMa scenario
115  testVector.m_positionA = Vector(0, 0, 35.0);
116  testVector.m_positionB = Vector(10, 0, 1.5);
117  testVector.m_pLos = 1;
118  testVector.m_typeId = ThreeGppRmaChannelConditionModel::GetTypeId();
119  m_testVectors.Add(testVector);
120 
121  testVector.m_positionA = Vector(0, 0, 35.0);
122  testVector.m_positionB = Vector(100, 0, 1.5);
123  testVector.m_pLos = exp(-(100.0 - 10.0) / 1000.0);
124  testVector.m_typeId = ThreeGppRmaChannelConditionModel::GetTypeId();
125  m_testVectors.Add(testVector);
126 
127  testVector.m_positionA = Vector(0, 0, 35.0);
128  testVector.m_positionB = Vector(1000, 0, 1.5);
129  testVector.m_pLos = exp(-(1000.0 - 10.0) / 1000.0);
130  testVector.m_typeId = ThreeGppRmaChannelConditionModel::GetTypeId();
131  m_testVectors.Add(testVector);
132 
133  // tests for the UMa scenario
134  testVector.m_positionA = Vector(0, 0, 25.0);
135  testVector.m_positionB = Vector(18, 0, 1.5);
136  testVector.m_pLos = 1;
137  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId();
138  m_testVectors.Add(testVector);
139 
140  testVector.m_positionA = Vector(0, 0, 25.0);
141  testVector.m_positionB = Vector(50, 0, 1.5);
142  testVector.m_pLos = (18.0 / 50.0 + exp(-50.0 / 63.0) * (1.0 - 18.0 / 50.0)) * (1.0 + 0);
143  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId();
144  m_testVectors.Add(testVector);
145 
146  testVector.m_positionA = Vector(0, 0, 25.0);
147  testVector.m_positionB = Vector(50, 0, 15);
148  testVector.m_pLos =
149  (18.0 / 50.0 + exp(-50.0 / 63.0) * (1.0 - 18.0 / 50.0)) *
150  (1.0 + pow(2.0 / 10.0, 1.5) * 5.0 / 4.0 * pow(50.0 / 100.0, 3) * exp(-50.0 / 150.0));
151  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId();
152  m_testVectors.Add(testVector);
153 
154  testVector.m_positionA = Vector(0, 0, 25.0);
155  testVector.m_positionB = Vector(100, 0, 1.5);
156  testVector.m_pLos = (18.0 / 100.0 + exp(-100.0 / 63.0) * (1.0 - 18.0 / 100.0)) * (1.0 + 0);
157  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId();
158  m_testVectors.Add(testVector);
159 
160  testVector.m_positionA = Vector(0, 0, 25.0);
161  testVector.m_positionB = Vector(100, 0, 15);
162  testVector.m_pLos = (18.0 / 100.0 + exp(-100.0 / 63.0) * (1.0 - 18.0 / 100.0)) *
163  (1.0 + pow(2.0 / 10.0, 1.5) * 5.0 / 4.0 * 1.0 * exp(-100.0 / 150.0));
164  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId();
165  m_testVectors.Add(testVector);
166 
167  // tests for the UMi-Street Canyon scenario
168  testVector.m_positionA = Vector(0, 0, 10.0);
169  testVector.m_positionB = Vector(18, 0, 1.5);
170  testVector.m_pLos = 1;
171  testVector.m_typeId = ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId();
172  m_testVectors.Add(testVector);
173 
174  testVector.m_positionA = Vector(0, 0, 10.0);
175  testVector.m_positionB = Vector(50, 0, 1.5);
176  testVector.m_pLos = (18.0 / 50.0 + exp(-50.0 / 36.0) * (1.0 - 18.0 / 50.0));
177  testVector.m_typeId = ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId();
178  m_testVectors.Add(testVector);
179 
180  m_testVectors.Add(testVector);
181  testVector.m_positionA = Vector(0, 0, 10.0);
182  testVector.m_positionB = Vector(100, 0, 15);
183  testVector.m_pLos = (18.0 / 100.0 + exp(-100.0 / 36.0) * (1.0 - 18.0 / 100.0));
184  testVector.m_typeId = ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId();
185  m_testVectors.Add(testVector);
186 
187  // tests for the Indoor Mixed Office scenario
188  testVector.m_positionA = Vector(0, 0, 2.0);
189  testVector.m_positionB = Vector(1.2, 0, 1.5);
190  testVector.m_pLos = 1;
191  testVector.m_typeId = ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId();
192  m_testVectors.Add(testVector);
193 
194  testVector.m_positionA = Vector(0, 0, 2.0);
195  testVector.m_positionB = Vector(5, 0, 1.5);
196  testVector.m_pLos = exp(-(5.0 - 1.2) / 4.7);
197  testVector.m_typeId = ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId();
198  m_testVectors.Add(testVector);
199 
200  testVector.m_positionA = Vector(0, 0, 2.0);
201  testVector.m_positionB = Vector(10, 0, 1.5);
202  testVector.m_pLos = exp(-(10.0 - 6.5) / 32.6) * 0.32;
203  testVector.m_typeId = ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId();
204  m_testVectors.Add(testVector);
205 
206  // tests for the Indoor Open Office scenario
207  testVector.m_positionA = Vector(0, 0, 3.0);
208  testVector.m_positionB = Vector(5, 0, 1.5);
209  testVector.m_pLos = 1;
210  testVector.m_typeId = ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId();
211  m_testVectors.Add(testVector);
212 
213  testVector.m_positionA = Vector(0, 0, 3.0);
214  testVector.m_positionB = Vector(30, 0, 1.5);
215  testVector.m_pLos = exp(-(30.0 - 5.0) / 70.8);
216  testVector.m_typeId = ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId();
217  m_testVectors.Add(testVector);
218 
219  testVector.m_positionA = Vector(0, 0, 3.0);
220  testVector.m_positionB = Vector(100, 0, 1.5);
221  testVector.m_pLos = exp(-(100.0 - 49.0) / 211.7) * 0.54;
222  testVector.m_typeId = ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId();
223  m_testVectors.Add(testVector);
224 
225  // create the factory for the channel condition models
226  ObjectFactory condModelFactory;
227 
228  // create the two nodes
230  nodes.Create(2);
231 
232  // create the mobility models
233  Ptr<MobilityModel> a = CreateObject<ConstantPositionMobilityModel>();
234  Ptr<MobilityModel> b = CreateObject<ConstantPositionMobilityModel>();
235 
236  // aggregate the nodes and the mobility models
237  nodes.Get(0)->AggregateObject(a);
238  nodes.Get(1)->AggregateObject(b);
239 
240  // Get the channel condition multiple times and compute the LOS probability
241  uint32_t numberOfReps = 500000;
242  for (uint32_t i = 0; i < m_testVectors.GetN(); ++i)
243  {
244  testVector = m_testVectors.Get(i);
245 
246  // set the distance between the two nodes
247  a->SetPosition(testVector.m_positionA);
248  b->SetPosition(testVector.m_positionB);
249 
250  // create the channel condition model
251  condModelFactory.SetTypeId(testVector.m_typeId);
252  m_condModel = condModelFactory.Create<ThreeGppChannelConditionModel>();
253  m_condModel->SetAttribute("UpdatePeriod", TimeValue(MilliSeconds(9)));
254 
255  m_numLos = 0;
256  for (uint32_t j = 0; j < numberOfReps; j++)
257  {
258  Simulator::Schedule(MilliSeconds(10 * j),
260  this,
261  a,
262  b);
263  }
264 
265  Simulator::Run();
266  Simulator::Destroy();
267 
268  double resultPlos = double(m_numLos) / double(numberOfReps);
269  NS_LOG_DEBUG(testVector.m_typeId << " a pos " << testVector.m_positionA << " b pos "
270  << testVector.m_positionB << " numLos " << m_numLos
271  << " numberOfReps " << numberOfReps << " resultPlos "
272  << resultPlos << " ref " << testVector.m_pLos);
273  NS_TEST_EXPECT_MSG_EQ_TOL(resultPlos,
274  testVector.m_pLos,
275  m_tolerance,
276  "Got unexpected LOS probability");
277  }
278 }
279 
286 {
287  public:
289 };
290 
292  : TestSuite("propagation-channel-condition-model", UNIT)
293 {
295 }
296 
static ChannelConditionModelsTestSuite g_channelConditionModelsTestSuite
Static variable for test initialization.
Test suite for the channel condition models.
Test case for the 3GPP channel condition models.
void DoRun() override
Builds the simulation scenario and perform the tests.
void EvaluateChannelCondition(Ptr< MobilityModel > a, Ptr< MobilityModel > b)
Evaluates the channel condition between two nodes by calling the method GetChannelCondition on m_cond...
Ptr< ThreeGppChannelConditionModel > m_condModel
the channel condition model
TestVectors< TestVector > m_testVectors
array containing all the test vectors
uint64_t m_numLos
the number of LOS occurrences
void SetPosition(const Vector &position)
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:204
Instantiate subclasses of ns3::Object.
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:259
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
A simple way to store test vectors (for stimulus or from responses)
Definition: test.h:1319
Base class for the 3GPP channel condition models.
Ptr< ChannelCondition > GetChannelCondition(Ptr< const MobilityModel > a, Ptr< const MobilityModel > b) const override
Retrieve the condition of the channel between a and b.
a unique identifier for an interface.
Definition: type-id.h:59
#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_TEST_EXPECT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report if ...
Definition: test.h:510
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
NodeContainer nodes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
TypeId m_typeId
the type ID of the channel condition model to be used