A Discrete-Event Network Simulator
API
channel-condition-model-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2019 SIGNET Lab, Department of Information Engineering,
4  * University of Padova
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */
19 
20 #include "ns3/log.h"
21 #include "ns3/abort.h"
22 #include "ns3/test.h"
23 #include "ns3/config.h"
24 #include "ns3/double.h"
25 #include "ns3/channel-condition-model.h"
26 #include "ns3/constant-position-mobility-model.h"
27 #include "ns3/simulator.h"
28 #include "ns3/node-container.h"
29 
30 using namespace ns3;
31 
32 NS_LOG_COMPONENT_DEFINE ("ChannelConditionModelsTest");
33 
41 {
42 public:
47 
52 
53 private:
57  virtual void DoRun (void);
58 
66  void EvaluateChannelCondition (Ptr<MobilityModel> a, Ptr<MobilityModel> b);
67 
71  typedef struct
72  {
73  Vector m_positionA;
74  Vector m_positionB;
75  double m_pLos;
77  } TestVector;
78 
81  uint64_t m_numLos;
82  double m_tolerance;
83 };
84 
86  : TestCase ("Test case for the child classes of ThreeGppChannelConditionModel"),
87  m_testVectors (),
88  m_tolerance (2e-3)
89 {
90 }
91 
93 {
94 }
95 
96 void
98 {
100  if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::LOS)
101  {
102  m_numLos++;
103  }
104 }
105 
106 void
108 {
109  // create the test vector
110  TestVector testVector;
111 
112  // tests for the RMa scenario
113  testVector.m_positionA = Vector (0, 0, 35.0);
114  testVector.m_positionB = Vector (10, 0, 1.5);
115  testVector.m_pLos = 1;
116  testVector.m_typeId = ThreeGppRmaChannelConditionModel::GetTypeId ();
117  m_testVectors.Add (testVector);
118 
119  testVector.m_positionA = Vector (0, 0, 35.0);
120  testVector.m_positionB = Vector (100, 0, 1.5);
121  testVector.m_pLos = exp (-(100.0 - 10.0) / 1000.0);
122  testVector.m_typeId = ThreeGppRmaChannelConditionModel::GetTypeId ();
123  m_testVectors.Add (testVector);
124 
125  testVector.m_positionA = Vector (0, 0, 35.0);
126  testVector.m_positionB = Vector (1000, 0, 1.5);
127  testVector.m_pLos = exp (-(1000.0 - 10.0) / 1000.0);
128  testVector.m_typeId = ThreeGppRmaChannelConditionModel::GetTypeId ();
129  m_testVectors.Add (testVector);
130 
131  // tests for the UMa scenario
132  testVector.m_positionA = Vector (0, 0, 25.0);
133  testVector.m_positionB = Vector (18, 0, 1.5);
134  testVector.m_pLos = 1;
135  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId ();
136  m_testVectors.Add (testVector);
137 
138  testVector.m_positionA = Vector (0, 0, 25.0);
139  testVector.m_positionB = Vector (50, 0, 1.5);
140  testVector.m_pLos = (18.0 / 50.0 + exp (-50.0 / 63.0) * (1.0 - 18.0 / 50.0)) * (1.0 + 0);
141  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId ();
142  m_testVectors.Add (testVector);
143 
144  testVector.m_positionA = Vector (0, 0, 25.0);
145  testVector.m_positionB = Vector (50, 0, 15);
146  testVector.m_pLos = (18.0 / 50.0 + exp (-50.0 / 63.0) * (1.0 - 18.0 / 50.0)) * (1.0 + pow (2.0 / 10.0, 1.5) * 5.0 / 4.0 * pow (50.0 / 100.0, 3) * exp (-50.0 / 150.0));
147  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId ();
148  m_testVectors.Add (testVector);
149 
150  testVector.m_positionA = Vector (0, 0, 25.0);
151  testVector.m_positionB = Vector (100, 0, 1.5);
152  testVector.m_pLos = (18.0 / 100.0 + exp (-100.0 / 63.0) * (1.0 - 18.0 / 100.0)) * (1.0 + 0);
153  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId ();
154  m_testVectors.Add (testVector);
155 
156  testVector.m_positionA = Vector (0, 0, 25.0);
157  testVector.m_positionB = Vector (100, 0, 15);
158  testVector.m_pLos = (18.0 / 100.0 + exp (-100.0 / 63.0) * (1.0 - 18.0 / 100.0)) * (1.0 + pow (2.0 / 10.0, 1.5) * 5.0 / 4.0 * 1.0 * exp (-100.0 / 150.0));
159  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId ();
160  m_testVectors.Add (testVector);
161 
162  // tests for the UMi-Street Canyon scenario
163  testVector.m_positionA = Vector (0, 0, 10.0);
164  testVector.m_positionB = Vector (18, 0, 1.5);
165  testVector.m_pLos = 1;
166  testVector.m_typeId = ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId ();
167  m_testVectors.Add (testVector);
168 
169  testVector.m_positionA = Vector (0, 0, 10.0);
170  testVector.m_positionB = Vector (50, 0, 1.5);
171  testVector.m_pLos = (18.0 / 50.0 + exp (-50.0 / 36.0) * (1.0 - 18.0 / 50.0));
172  testVector.m_typeId = ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId ();
173  m_testVectors.Add (testVector);
174 
175  m_testVectors.Add (testVector);
176  testVector.m_positionA = Vector (0, 0, 10.0);
177  testVector.m_positionB = Vector (100, 0, 15);
178  testVector.m_pLos = (18.0 / 100.0 + exp (-100.0 / 36.0) * (1.0 - 18.0 / 100.0));
179  testVector.m_typeId = ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId ();
180  m_testVectors.Add (testVector);
181 
182  // tests for the Indoor Mixed Office scenario
183  testVector.m_positionA = Vector (0, 0, 2.0);
184  testVector.m_positionB = Vector (1.2, 0, 1.5);
185  testVector.m_pLos = 1;
186  testVector.m_typeId = ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId ();
187  m_testVectors.Add (testVector);
188 
189  testVector.m_positionA = Vector (0, 0, 2.0);
190  testVector.m_positionB = Vector (5, 0, 1.5);
191  testVector.m_pLos = exp (-(5.0 - 1.2) / 4.7);
192  testVector.m_typeId = ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId ();
193  m_testVectors.Add (testVector);
194 
195  testVector.m_positionA = Vector (0, 0, 2.0);
196  testVector.m_positionB = Vector (10, 0, 1.5);
197  testVector.m_pLos = exp (-(10.0 - 6.5) / 32.6) * 0.32;
198  testVector.m_typeId = ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId ();
199  m_testVectors.Add (testVector);
200 
201  // tests for the Indoor Open Office scenario
202  testVector.m_positionA = Vector (0, 0, 3.0);
203  testVector.m_positionB = Vector (5, 0, 1.5);
204  testVector.m_pLos = 1;
205  testVector.m_typeId = ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId ();
206  m_testVectors.Add (testVector);
207 
208  testVector.m_positionA = Vector (0, 0, 3.0);
209  testVector.m_positionB = Vector (30, 0, 1.5);
210  testVector.m_pLos = exp (-(30.0 - 5.0) / 70.8);
211  testVector.m_typeId = ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId ();
212  m_testVectors.Add (testVector);
213 
214  testVector.m_positionA = Vector (0, 0, 3.0);
215  testVector.m_positionB = Vector (100, 0, 1.5);
216  testVector.m_pLos = exp (-(100.0 - 49.0) / 211.7) * 0.54;
217  testVector.m_typeId = ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId ();
218  m_testVectors.Add (testVector);
219 
220  // create the factory for the channel condition models
221  ObjectFactory condModelFactory;
222 
223  // create the two nodes
225  nodes.Create (2);
226 
227  // create the mobility models
228  Ptr<MobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
229  Ptr<MobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
230 
231  // aggregate the nodes and the mobility models
232  nodes.Get (0)->AggregateObject (a);
233  nodes.Get (1)->AggregateObject (b);
234 
235  // Get the channel condition multiple times and compute the LOS probability
236  uint32_t numberOfReps = 500000;
237  for (uint32_t i = 0; i < m_testVectors.GetN (); ++i)
238  {
239  testVector = m_testVectors.Get (i);
240 
241  // set the distance between the two nodes
242  a->SetPosition (testVector.m_positionA);
243  b->SetPosition (testVector.m_positionB);
244 
245  // create the channel condition model
246  condModelFactory.SetTypeId (testVector.m_typeId);
247  m_condModel = condModelFactory.Create<ThreeGppChannelConditionModel> ();
248  m_condModel->SetAttribute ("UpdatePeriod", TimeValue (MilliSeconds (9)));
249 
250  m_numLos = 0;
251  for (uint32_t j = 0; j < numberOfReps; j++)
252  {
253  Simulator::Schedule (MilliSeconds (10 * j), &ThreeGppChannelConditionModelTestCase::EvaluateChannelCondition, this, a, b);
254  }
255 
256  Simulator::Run ();
257  Simulator::Destroy ();
258 
259  double resultPlos = double (m_numLos) / double (numberOfReps);
260  NS_LOG_DEBUG (testVector.m_typeId << " a pos " << testVector.m_positionA << " b pos " << testVector.m_positionB << " numLos " << m_numLos << " numberOfReps " << numberOfReps << " resultPlos " << resultPlos << " ref " << testVector.m_pLos);
261  NS_TEST_EXPECT_MSG_EQ_TOL (resultPlos, testVector.m_pLos, m_tolerance, "Got unexpected LOS probability");
262  }
263 }
264 
269 {
270 public:
272 };
273 
275  : TestSuite ("propagation-channel-condition-model", UNIT)
276 {
277  AddTestCase (new ThreeGppChannelConditionModelTestCase, TestCase::QUICK);
278 }
279 
static ChannelConditionModelsTestSuite ChannelConditionModelsTestSuite
Test suite for the channel condition models.
Test case for the 3GPP channel condition models.
virtual void DoRun(void)
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 SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
Instantiate subclasses of ns3::Object.
Ptr< Object > Create(void) 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.
encapsulates test code
Definition: test.h:1154
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1344
A simple way to store test vectors (for stimulus or from responses)
Definition: test.h:1407
Base class for the 3GPP channel condition models.
virtual Ptr< ChannelCondition > GetChannelCondition(Ptr< const MobilityModel > a, Ptr< const MobilityModel > b) const override
Retrieve the condition of the channel between a and b.
AttributeValue implementation for Time.
Definition: nstime.h:1353
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:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#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:563
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
nodes
Definition: first.py:32
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