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 
43 {
44 public:
49 
54 
55 private:
59  virtual void DoRun (void);
60 
68  void EvaluateChannelCondition (Ptr<MobilityModel> a, Ptr<MobilityModel> b);
69 
73  typedef struct
74  {
75  Vector m_positionA;
76  Vector m_positionB;
77  double m_pLos;
79  } TestVector;
80 
83  uint64_t m_numLos;
84  double m_tolerance;
85 };
86 
88  : TestCase ("Test case for the child classes of ThreeGppChannelConditionModel"),
89  m_testVectors (),
90  m_tolerance (2e-3)
91 {
92 }
93 
95 {
96 }
97 
98 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 = (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));
149  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId ();
150  m_testVectors.Add (testVector);
151 
152  testVector.m_positionA = Vector (0, 0, 25.0);
153  testVector.m_positionB = Vector (100, 0, 1.5);
154  testVector.m_pLos = (18.0 / 100.0 + exp (-100.0 / 63.0) * (1.0 - 18.0 / 100.0)) * (1.0 + 0);
155  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId ();
156  m_testVectors.Add (testVector);
157 
158  testVector.m_positionA = Vector (0, 0, 25.0);
159  testVector.m_positionB = Vector (100, 0, 15);
160  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));
161  testVector.m_typeId = ThreeGppUmaChannelConditionModel::GetTypeId ();
162  m_testVectors.Add (testVector);
163 
164  // tests for the UMi-Street Canyon scenario
165  testVector.m_positionA = Vector (0, 0, 10.0);
166  testVector.m_positionB = Vector (18, 0, 1.5);
167  testVector.m_pLos = 1;
168  testVector.m_typeId = ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId ();
169  m_testVectors.Add (testVector);
170 
171  testVector.m_positionA = Vector (0, 0, 10.0);
172  testVector.m_positionB = Vector (50, 0, 1.5);
173  testVector.m_pLos = (18.0 / 50.0 + exp (-50.0 / 36.0) * (1.0 - 18.0 / 50.0));
174  testVector.m_typeId = ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId ();
175  m_testVectors.Add (testVector);
176 
177  m_testVectors.Add (testVector);
178  testVector.m_positionA = Vector (0, 0, 10.0);
179  testVector.m_positionB = Vector (100, 0, 15);
180  testVector.m_pLos = (18.0 / 100.0 + exp (-100.0 / 36.0) * (1.0 - 18.0 / 100.0));
181  testVector.m_typeId = ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId ();
182  m_testVectors.Add (testVector);
183 
184  // tests for the Indoor Mixed Office scenario
185  testVector.m_positionA = Vector (0, 0, 2.0);
186  testVector.m_positionB = Vector (1.2, 0, 1.5);
187  testVector.m_pLos = 1;
188  testVector.m_typeId = ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId ();
189  m_testVectors.Add (testVector);
190 
191  testVector.m_positionA = Vector (0, 0, 2.0);
192  testVector.m_positionB = Vector (5, 0, 1.5);
193  testVector.m_pLos = exp (-(5.0 - 1.2) / 4.7);
194  testVector.m_typeId = ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId ();
195  m_testVectors.Add (testVector);
196 
197  testVector.m_positionA = Vector (0, 0, 2.0);
198  testVector.m_positionB = Vector (10, 0, 1.5);
199  testVector.m_pLos = exp (-(10.0 - 6.5) / 32.6) * 0.32;
200  testVector.m_typeId = ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId ();
201  m_testVectors.Add (testVector);
202 
203  // tests for the Indoor Open Office scenario
204  testVector.m_positionA = Vector (0, 0, 3.0);
205  testVector.m_positionB = Vector (5, 0, 1.5);
206  testVector.m_pLos = 1;
207  testVector.m_typeId = ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId ();
208  m_testVectors.Add (testVector);
209 
210  testVector.m_positionA = Vector (0, 0, 3.0);
211  testVector.m_positionB = Vector (30, 0, 1.5);
212  testVector.m_pLos = exp (-(30.0 - 5.0) / 70.8);
213  testVector.m_typeId = ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId ();
214  m_testVectors.Add (testVector);
215 
216  testVector.m_positionA = Vector (0, 0, 3.0);
217  testVector.m_positionB = Vector (100, 0, 1.5);
218  testVector.m_pLos = exp (-(100.0 - 49.0) / 211.7) * 0.54;
219  testVector.m_typeId = ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId ();
220  m_testVectors.Add (testVector);
221 
222  // create the factory for the channel condition models
223  ObjectFactory condModelFactory;
224 
225  // create the two nodes
227  nodes.Create (2);
228 
229  // create the mobility models
230  Ptr<MobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
231  Ptr<MobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
232 
233  // aggregate the nodes and the mobility models
234  nodes.Get (0)->AggregateObject (a);
235  nodes.Get (1)->AggregateObject (b);
236 
237  // Get the channel condition multiple times and compute the LOS probability
238  uint32_t numberOfReps = 500000;
239  for (uint32_t i = 0; i < m_testVectors.GetN (); ++i)
240  {
241  testVector = m_testVectors.Get (i);
242 
243  // set the distance between the two nodes
244  a->SetPosition (testVector.m_positionA);
245  b->SetPosition (testVector.m_positionB);
246 
247  // create the channel condition model
248  condModelFactory.SetTypeId (testVector.m_typeId);
249  m_condModel = condModelFactory.Create<ThreeGppChannelConditionModel> ();
250  m_condModel->SetAttribute ("UpdatePeriod", TimeValue (MilliSeconds (9)));
251 
252  m_numLos = 0;
253  for (uint32_t j = 0; j < numberOfReps; j++)
254  {
255  Simulator::Schedule (MilliSeconds (10 * j), &ThreeGppChannelConditionModelTestCase::EvaluateChannelCondition, this, a, b);
256  }
257 
258  Simulator::Run ();
259  Simulator::Destroy ();
260 
261  double resultPlos = double (m_numLos) / double (numberOfReps);
262  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);
263  NS_TEST_EXPECT_MSG_EQ_TOL (resultPlos, testVector.m_pLos, m_tolerance, "Got unexpected LOS probability");
264  }
265 }
266 
273 {
274 public:
276 };
277 
279  : TestSuite ("propagation-channel-condition-model", UNIT)
280 {
281  AddTestCase (new ThreeGppChannelConditionModelTestCase, TestCase::QUICK);
282 }
283 
static ChannelConditionModelsTestSuite g_channelConditionModelsTestSuite
Static variable for test initialization.
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:256
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:994
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:1188
A simple way to store test vectors (for stimulus or from responses)
Definition: test.h:1251
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:1308
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:491
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
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