A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
29using namespace ns3;
30
31NS_LOG_COMPONENT_DEFINE("ChannelConditionModelsTest");
32
33/**
34 * \ingroup propagation-tests
35 *
36 * Test case for the 3GPP channel condition models. It determines the
37 * channel condition multiple times, estimates the LOS probability and
38 * compares it with the value given by the formulas in 3GPP TR 38.901,
39 * Table Table 7.4.2-1.
40 */
42{
43 public:
44 /**
45 * Constructor
46 */
48
49 /**
50 * Destructor
51 */
53
54 private:
55 /**
56 * Builds the simulation scenario and perform the tests
57 */
58 void DoRun() override;
59
60 /**
61 * Evaluates the channel condition between two nodes by calling the method
62 * GetChannelCondition on m_condModel. If the channel condition is LOS it
63 * increments m_numLos
64 * \param a the mobility model of the first node
65 * \param b the mobility model of the second node
66 */
68
69 /**
70 * Struct containing the parameters for each test
71 */
73 {
74 Vector m_positionA; //!< the position of the first node
75 Vector m_positionB; //!< the position of the second node
76 double m_pLos; //!< LOS probability
77 TypeId m_typeId; //!< the type ID of the channel condition model to be used
78 };
79
80 TestVectors<TestVector> m_testVectors; //!< array containing all the test vectors
81 Ptr<ThreeGppChannelConditionModel> m_condModel; //!< the channel condition model
82 uint64_t m_numLos; //!< the number of LOS occurrences
83 double m_tolerance; //!< 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
97void
100{
102 if (cond->GetLosCondition() == ChannelCondition::LosConditionValue::LOS)
103 {
104 m_numLos++;
105 }
106}
107
108void
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;
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);
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);
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;
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);
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));
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);
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));
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;
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));
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));
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;
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);
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;
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;
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);
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;
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
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);
253 m_condModel->SetAttribute("UpdatePeriod", TimeValue(MilliSeconds(9)));
254
255 m_numLos = 0;
256 for (uint32_t j = 0; j < numberOfReps; j++)
257 {
260 this,
261 a,
262 b);
263 }
264
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,
276 "Got unexpected LOS probability");
277 }
278}
279
280/**
281 * \ingroup propagation-tests
282 *
283 * Test suite for the channel condition models
284 */
286{
287 public:
289};
290
292 : TestSuite("propagation-channel-condition-model", Type::UNIT)
293{
294 AddTestCase(new ThreeGppChannelConditionModelTestCase, TestCase::Duration::QUICK);
295}
296
297/// Static variable for test initialization
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
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:211
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:309
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static void Run()
Run the simulation.
Definition: simulator.cc:178
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
A simple way to store test vectors (for stimulus or from responses)
Definition: test.h:1342
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.
static TypeId GetTypeId()
Get the type ID.
static TypeId GetTypeId()
Get the type ID.
AttributeValue implementation for Time.
Definition: nstime.h:1413
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:511
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