A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wraparound-model-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2025 CTTC
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Gabriel Ferreira <gabrielcarvfer@gmail.com>
7 */
8
9#include "ns3/boolean.h"
10#include "ns3/config.h"
11#include "ns3/hexagonal-wraparound-model.h"
12#include "ns3/mobility-helper.h"
13#include "ns3/node-container.h"
14#include "ns3/simulator.h"
15#include "ns3/test.h"
16#include "ns3/waypoint-mobility-model.h"
17
18using namespace ns3;
19
20/**
21 * @ingroup propagation-test
22 *
23 * @brief Wraparound Model Test
24 */
26{
27 public:
28 /**
29 * Constructor for test case
30 * @param name description of test case
31 * @param numRings number of rings used in the deployment
32 * @param alternativeConfig wraparound is configured manually when false, or via constructor
33 * when true.
34 */
35 WraparoundModelTest(std::string name, int numRings, bool alternativeConfig)
36 : TestCase(name),
37 m_numRings(numRings),
38 m_alternativeConfig(alternativeConfig)
39 {
40 }
41
42 private:
43 int m_numRings; ///< number of wrings to wraparound
44 bool m_alternativeConfig; ///< indicate whether to configure isd and numSites via constructor or
45 ///< manually
46 private:
47 void DoRun() override;
48};
49
50size_t
51GetNearestSite(std::vector<Vector3D>& sites, size_t numSites, Vector3D virtualPos)
52{
53 double minDist = std::numeric_limits<double>::max();
54 size_t minSite = 0;
55 for (size_t siteI = 0; siteI < sites.size() && siteI < numSites; siteI++)
56 {
57 auto dist = CalculateDistance(sites.at(siteI), virtualPos);
58 if (dist < minDist)
59 {
60 minDist = dist;
61 minSite = siteI;
62 }
63 }
64 return minSite;
65}
66
67void
69{
70 int numSites = 0;
71 switch (m_numRings)
72 {
73 case 0:
74 numSites = 1;
75 break;
76 case 1:
77 numSites = 7;
78 break;
79 case 3:
80 numSites = 19;
81 break;
82 default:
84 true,
85 "Wraparound does not support " << m_numRings << " rings");
86 break;
87 }
88
89 NodeContainer userNodes(1);
90 NodeContainer siteNodes(numSites);
91
92 MobilityHelper mobilityHelper;
93 mobilityHelper.SetMobilityModel("ns3::ConstantPositionMobilityModel");
94
95 // Site positions
96 // clang-format off
97 std::vector<Vector3D> sitePositions = {
98 Vector3D( 0, 0, 30), // Site 01
99 Vector3D( 1000, 0, 30), // Site 02
100 Vector3D( 500, 866, 30), // Site 03
101 Vector3D( -500, 866, 30), // Site 04
102 Vector3D(-1000, 0, 30), // Site 05
103 Vector3D( -500, -866, 30), // Site 06
104 Vector3D( 500, -866, 30), // Site 07
105 Vector3D( 2000, 0, 30), // Site 08
106 Vector3D( 1500, 866, 30), // Site 09
107 Vector3D( 500, 1732, 30), // Site 10
108 Vector3D( -500, 1732, 30), // Site 11
109 Vector3D(-1500, 866, 30), // Site 12
110 Vector3D(-2000, 0, 30), // Site 13
111 Vector3D(-1500, -866, 30), // Site 14
112 Vector3D( -500, -1732, 30), // Site 15
113 Vector3D( 500, -1732, 30), // Site 16
114 Vector3D( 1500, -866, 30), // Site 17
115 Vector3D( 1000, 1732, 30), // Site 18
116 Vector3D(-1000, 1732, 30), // Site 19
117 };
118 // clang-format on
119
120 Ptr<HexagonalWraparoundModel> wraparoundModel =
123
125 {
126 wraparoundModel->SetSiteDistance(1000);
127 wraparoundModel->SetNumSites(numSites);
128 auto sitePositionsSlice =
129 std::vector<Vector3D>(sitePositions.begin(), sitePositions.begin() + numSites);
130 wraparoundModel->SetSitePositions(sitePositionsSlice);
131 }
132
133 // Install mobility models
134 mobilityHelper.Install(userNodes);
135 mobilityHelper.Install(siteNodes);
136
137 // Add site positions and wraparound model
138 for (auto i = 0; i < numSites; i++)
139 {
140 auto siteMm = siteNodes.Get(i)->GetObject<MobilityModel>();
141 siteMm->SetPosition(sitePositions.at(i));
143 {
144 wraparoundModel->AddSitePosition(sitePositions.at(i));
145 }
146 }
147
148 // Retrieve user node mobility to move it around
149 auto userMm = userNodes.Get(0)->GetObject<MobilityModel>();
150
151 // Test cases (target site number, expected UE virtual site, real user position, expected
152 // wrapped position)
153 std::vector<std::tuple<size_t, size_t, Vector3D, Vector3D>> testPoint;
154 // clang-format off
155 switch (m_numRings)
156 {
157 case 3: // Cases involving sites 8-19
158 testPoint.emplace_back( 7, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
159 testPoint.emplace_back( 8, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
160 testPoint.emplace_back( 9, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
161 testPoint.emplace_back(10, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
162 testPoint.emplace_back(11, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
163 testPoint.emplace_back(12, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
164 testPoint.emplace_back(13, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
165 testPoint.emplace_back(14, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
166 testPoint.emplace_back(15, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
167 testPoint.emplace_back(16, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
168 testPoint.emplace_back(17, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
169 testPoint.emplace_back(18, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
170 testPoint.emplace_back( 7, 0, Vector3D( 100, 0, 0), Vector3D( 100, 0, 0));
171 testPoint.emplace_back( 8, 0, Vector3D( 500, 0, 0), Vector3D( 500, 0, 0));
172 testPoint.emplace_back( 9, 1, Vector3D( 1000, 0, 0), Vector3D( 1000, 0, 0));
173 testPoint.emplace_back(10, 2, Vector3D( 1000, 1000, 0), Vector3D( 1000, 1000, 0));
174 testPoint.emplace_back(11, 0, Vector3D( -500, 0, 0), Vector3D( -500, 0, 0));
175 testPoint.emplace_back(12, 0, Vector3D( 0, -500, 0), Vector3D( 0, -500, 0));
176 testPoint.emplace_back(13, 5, Vector3D(-1000, -1000, 0), Vector3D(-1000, -1000, 0));
177 testPoint.emplace_back(14, 13, Vector3D( 2000, -1000, 0), Vector3D(-2330, -1500, 0));
178 testPoint.emplace_back(15, 16, Vector3D(-1000, 2000, 0), Vector3D( 1598, -1500, 0));
179 testPoint.emplace_back(16, 15, Vector3D( 2000, 2000, 0), Vector3D( 267, -2000, 0));
180 testPoint.emplace_back(17, 10, Vector3D(-2000, -2000, 0), Vector3D( -268, 2000, 0));
181 testPoint.emplace_back(18, 11, Vector3D(-2000, 1500, 0), Vector3D(-2000, 1500, 0));
182 break;
183 case 1: // Cases involving sites 2-7
184 testPoint.emplace_back(1, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
185 testPoint.emplace_back(2, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
186 testPoint.emplace_back(3, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
187 testPoint.emplace_back(4, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
188 testPoint.emplace_back(5, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
189 testPoint.emplace_back(6, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
190 testPoint.emplace_back(1, 1, Vector3D( 1000, 0, 0), Vector3D( 1000, 0, 0));
191 testPoint.emplace_back(2, 3, Vector3D( 1000, -500, 0), Vector3D( -732, 1500, 0));
192 testPoint.emplace_back(3, 4, Vector3D( 1000, 500, 0), Vector3D(-1598, 0, 0));
193 testPoint.emplace_back(4, 4, Vector3D(-1000, 0, 0), Vector3D(-1000, 0, 0));
194 testPoint.emplace_back(5, 6, Vector3D(-1000, 500, 0), Vector3D( 732, -1500, 0));
195 testPoint.emplace_back(6, 1, Vector3D(-1000, -500, 0), Vector3D( 1598, 0, 0));
196 break;
197 case 0: // Cases involving site 1. No wraparound.
198 testPoint.emplace_back(0, 0, Vector3D( 0, 0, 0), Vector3D( 0, 0, 0));
199 testPoint.emplace_back(0, 0, Vector3D( 1000, 1000, 0), Vector3D( 1000, 1000, 0));
200 testPoint.emplace_back(0, 0, Vector3D( 1000, -1000, 0), Vector3D( 1000, -1000, 0));
201 testPoint.emplace_back(0, 0, Vector3D(-1000, 1000, 0), Vector3D(-1000, 1000, 0));
202 testPoint.emplace_back(0, 0, Vector3D(-1000, -1000, 0), Vector3D(-1000, -1000, 0));
203 testPoint.emplace_back(0, 0, Vector3D( 2000, 2000, 0), Vector3D( 2000, 2000, 0));
204 testPoint.emplace_back(0, 0, Vector3D( 2000, -2000, 0), Vector3D( 2000, -2000, 0));
205 testPoint.emplace_back(0, 0, Vector3D(-2000, 2000, 0), Vector3D(-2000, 2000, 0));
206 testPoint.emplace_back(0, 0, Vector3D(-2000, -2000, 0), Vector3D(-2000, -2000, 0));
207 default:
208 break;
209 }
210 // clang-format on
211
212 for (auto [siteNumber, expectedVirtualUserSite, realUserPos, expectedVirtualPos] : testPoint)
213 {
214 userMm->SetPosition(realUserPos);
215 auto siteMm = siteNodes.Get(siteNumber)->GetObject<MobilityModel>();
216 auto virtualPos =
217 wraparoundModel->GetVirtualPosition(userMm->GetPosition(), siteMm->GetPosition());
218 auto nearestSiteToVirtualUser = GetNearestSite(sitePositions, numSites, virtualPos);
219 NS_TEST_EXPECT_MSG_EQ(nearestSiteToVirtualUser,
220 expectedVirtualUserSite,
221 "Virtual position leads to from real site "
222 << GetNearestSite(sitePositions, numSites, realUserPos)
223 << " to incorrect site " << nearestSiteToVirtualUser);
224 NS_TEST_EXPECT_MSG_LT_OR_EQ(CalculateDistance(virtualPos, expectedVirtualPos),
225 5,
226 "Expected " << expectedVirtualPos << " and obtained "
227 << virtualPos << " virtual positions differ");
228 }
229 // Move user node and check virtual positions correspond to the expected sites
233}
234
235/**
236 * @ingroup propagation-test
237 *
238 * @brief Wraparound Model Test Suite
239 */
241{
243 : TestSuite("wraparound-model", Type::UNIT)
244 {
245 std::vector<bool> alternativeConfig{false, true};
246 for (auto altConf : alternativeConfig)
247 {
248 // Supported ring numbers
249 AddTestCase(new WraparoundModelTest("Check wraparound with 0 rings", 0, altConf),
251 AddTestCase(new WraparoundModelTest("Check wraparound with 1 rings", 1, altConf),
253 AddTestCase(new WraparoundModelTest("Check wraparound with 3 rings", 3, altConf),
255 }
256 }
257} g_WraparoundModelTestSuite; ///< the test suite
Wraparound Model Test.
WraparoundModelTest(std::string name, int numRings, bool alternativeConfig)
Constructor for test case.
bool m_alternativeConfig
indicate whether to configure isd and numSites via constructor or manually
int m_numRings
number of wrings to wraparound
void DoRun() override
Implementation to actually run this TestCase.
Helper class used to assign positions and mobility models to nodes.
void Install(Ptr< Node > node) const
"Layout" a single node according to the current position allocator type.
void SetMobilityModel(std::string type, Ts &&... args)
Keep track of the current position and velocity of an object.
void SetPosition(const Vector &position)
keep track of a set of node pointers.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
@ QUICK
Fast test.
Definition test.h:1054
TestCase(const TestCase &)=delete
Type
Type of test.
Definition test.h:1257
@ UNIT
This test suite implements a Unit Test.
Definition test.h:1259
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:490
a 3d vector
Definition vector.h:35
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
WraparoundModelTestSuite g_WraparoundModelTestSuite
the test suite
#define NS_TEST_EXPECT_MSG_LT_OR_EQ(actual, limit, msg)
Test that an actual value is less than or equal to a limit and report if not.
Definition test.h:819
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition test.h:240
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double CalculateDistance(const Vector3D &a, const Vector3D &b)
Definition vector.cc:98
size_t GetNearestSite(std::vector< Vector3D > &sites, size_t numSites, Vector3D virtualPos)