5#include "hexagonal-grid-scenario-helper.h"
7#include "ns3/constant-velocity-mobility-model.h"
9#include <ns3/mobility-helper.h>
17HexagonalGridScenarioHelper::SetResultsDir(std::string resultsDir)
19 m_resultsDir = resultsDir;
23HexagonalGridScenarioHelper::SetSimTag(std::string simTag)
30 m_r = CreateObject<UniformRandomVariable>();
31 m_theta = CreateObject<UniformRandomVariable>();
38const double distTo2ndRing = std::sqrt(3);
39const double distTo4thRing = std::sqrt(7);
41std::vector<double> HexagonalGridScenarioHelper::siteDistances{0,
110const double ang4thRingAlpha1 = atan2(1, (3 * sqrt(3))) * (180 / M_PI);
112const double ang4thRingAlpha2 = 90 - atan2(sqrt(3), 2) * (180 / M_PI);
114const double ang4thRingAlpha3 = 90 - atan2(3, (5 * sqrt(3))) * (180 / M_PI);
116std::vector<double> HexagonalGridScenarioHelper::siteAngles{
139 180 - ang4thRingAlpha3,
140 180 - ang4thRingAlpha2,
141 180 - ang4thRingAlpha1,
142 180 + ang4thRingAlpha1,
143 180 + ang4thRingAlpha2,
144 180 + ang4thRingAlpha3,
167PlotHexagonalDeployment(
const Ptr<const ListPositionAllocator>& sitePosVector,
168 const Ptr<const ListPositionAllocator>& cellCenterVector,
169 const Ptr<const ListPositionAllocator>& utPosVector,
171 std::string resultsDir,
174 uint16_t numCells = cellCenterVector->GetSize();
175 uint16_t numSites = sitePosVector->GetSize();
176 uint16_t numSectors = numCells / numSites;
177 uint16_t numUts = utPosVector->GetSize();
178 NS_ASSERT_MSG(numCells > 0,
"no cells");
179 NS_ASSERT_MSG(numSites > 0,
"no sites");
180 NS_ASSERT_MSG(numUts > 0,
"no uts");
183 std::ofstream topologyOutfile;
184 std::string topologyFileRoot = resultsDir +
"./hexagonal-topology";
185 std::string topologyFileName = topologyFileRoot + simTag +
".gnuplot";
186 topologyOutfile.open(topologyFileName.c_str(), std::ios_base::out | std::ios_base::trunc);
187 if (!topologyOutfile.is_open())
189 NS_ABORT_MSG(
"Can't open " << topologyFileName);
192 topologyOutfile <<
"set term pdf" << std::endl;
193 topologyOutfile <<
"set output \"" << topologyFileName <<
".pdf\"" << std::endl;
194 topologyOutfile <<
"set style arrow 1 lc \"black\" lt 1 head filled" << std::endl;
198 (12 * cellRadius) + 1;
199 topologyOutfile <<
"set xrange [-" << margin <<
":" << margin <<
"]" << std::endl;
200 topologyOutfile <<
"set yrange [-" << margin <<
":" << margin <<
"]" << std::endl;
206 std::vector<double> hx{0.0, -0.5, -0.5, 0.0, 0.5, 0.5, 0.0};
207 std::vector<double> hy{-1.0, -0.5, 0.5, 1.0, 0.5, -0.5, -1.0};
210 for (uint16_t cellId = 0; cellId < numCells; ++cellId)
212 Vector cellPos = cellCenterVector->GetNext();
213 double angleDeg = 30 + 120 * (cellId % 3);
214 double angleRad = angleDeg * M_PI / 180;
218 if (cellId % numSectors == 0)
220 sitePos = sitePosVector->GetNext();
222 topologyOutfile <<
"set arrow " << cellId + 1 <<
" from " << sitePos.x <<
"," << sitePos.y
223 <<
" rto " << arrowLength * std::cos(angleRad) <<
","
224 << arrowLength * std::sin(angleRad) <<
" arrowstyle 1 \n";
227 topologyOutfile <<
"set object " << cellId + 1 <<
" polygon from \\\n";
229 for (uint16_t vertexId = 0; vertexId <= 6; ++vertexId)
232 x = cellRadius * std::sqrt(3.0) * hx.at(vertexId) + cellPos.x;
233 y = cellRadius * hy.at(vertexId) + cellPos.y;
234 topologyOutfile << x <<
", " << y;
237 topologyOutfile <<
" front fs empty \n";
241 topologyOutfile <<
" to \\\n";
245 topologyOutfile <<
"set label " << cellId + 1 <<
" \"" << (cellId + 1) <<
"\" at "
246 << cellPos.x <<
" , " << cellPos.y <<
" center" << std::endl;
249 for (uint16_t utId = 0; utId < numUts; ++utId)
251 Vector utPos = utPosVector->GetNext();
253 topologyOutfile <<
"set label at " << utPos.x <<
" , " << utPos.y
254 <<
" point pointtype 7 pointsize 0.2 center" << std::endl;
257 topologyOutfile <<
"unset key" << std::endl;
258 topologyOutfile <<
"plot 1/0" << std::endl;
262GetClosestSitePosition(Vector cellCenterPos,
const Ptr<ListPositionAllocator>& sitePosVector)
264 double minDistance = UINT32_MAX;
265 Vector closestSitePosition;
267 for (uint32_t i = 0; i < sitePosVector->GetSize(); i++)
269 Vector sitePos = sitePosVector->GetNext();
270 double d_x = sitePos.x - cellCenterPos.x;
271 double d_y = sitePos.y - cellCenterPos.y;
272 double distance2D = sqrt(d_x * d_x + d_y * d_y);
273 if (distance2D < minDistance)
275 minDistance = distance2D;
276 closestSitePosition = sitePos;
280 NS_ABORT_MSG_IF(minDistance == UINT32_MAX,
281 "Get closest site position function not executed properly.");
282 return closestSitePosition;
288 NS_ABORT_MSG_IF(numRings > 5,
"Unsupported number of outer rings (Maximum is 5");
290 m_numRings = numRings;
327 return m_hexagonalRadius;
333 Vector center(sitePos);
339 NS_ABORT_MSG(
"Number of sectors has not been defined");
349 center.x += m_hexagonalRadius * std::sqrt(0.75);
350 center.y += m_hexagonalRadius / 2;
354 center.x -= m_hexagonalRadius * std::sqrt(0.75);
355 center.y += m_hexagonalRadius / 2;
359 center.y -= m_hexagonalRadius;
363 NS_ABORT_MSG(
"Unknown sector number: " <<
GetSectorIndex(cellId));
368 NS_ABORT_MSG(
"Unsupported number of sectors");
378 m_hexagonalRadius =
m_isd / 3;
383 NS_ASSERT(
m_isd > 0);
384 NS_ASSERT(m_numRings < 6);
385 NS_ASSERT(m_hexagonalRadius > 0);
388 NS_ASSERT(
m_bs.GetN() > 0);
389 NS_ASSERT(
m_ut.GetN() > 0);
391 MobilityHelper mobility;
392 Ptr<ListPositionAllocator> bsPosVector = CreateObject<ListPositionAllocator>();
393 Ptr<ListPositionAllocator> bsCenterVector = CreateObject<ListPositionAllocator>();
394 Ptr<ListPositionAllocator> sitePosVector = CreateObject<ListPositionAllocator>();
395 Ptr<ListPositionAllocator> utPosVector = CreateObject<ListPositionAllocator>();
398 for (std::size_t cellId = 0; cellId <
m_numBs; cellId++)
401 Vector sitePos(m_centralPos);
402 const double dist = siteDistances.at(siteIndex);
403 const double angleRad = siteAngles.at(siteIndex) * M_PI / 180;
404 sitePos.x +=
m_isd * dist * cos(angleRad);
405 sitePos.y +=
m_isd * dist * sin(angleRad);
410 sitePosVector->Add(sitePos);
417 bsPosVector->Add(bsPos);
421 bsCenterVector->Add(cellCenterPos);
437 const double outerR = (std::sqrt(3) / 2) * m_hexagonalRadius -
m_minBsUtDistance;
438 m_r->SetAttribute(
"Min", DoubleValue(0));
439 m_r->SetAttribute(
"Max", DoubleValue(outerR * outerR));
440 m_theta->SetAttribute(
"Min", DoubleValue(-1.0 * M_PI));
441 m_theta->SetAttribute(
"Max", DoubleValue(M_PI));
445 for (uint32_t utId = 0; utId <
m_ut.GetN(); ++utId)
447 double d = std::sqrt(m_r->GetValue());
448 double t = m_theta->GetValue();
451 Vector utPos(bsCenterVector->GetNext());
452 utPos.x += d * cos(t);
453 utPos.y += d * sin(t);
456 utPosVector->Add(utPos);
459 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
460 mobility.SetPositionAllocator(bsPosVector);
461 mobility.Install(
m_bs);
463 mobility.SetPositionAllocator(utPosVector);
464 mobility.Install(
m_ut);
466 PlotHexagonalDeployment(sitePosVector,
477 m_hexagonalRadius =
m_isd / 3;
482 NS_ASSERT(
m_isd > 0);
483 NS_ASSERT(m_numRings < 6);
484 NS_ASSERT(m_hexagonalRadius > 0);
487 NS_ASSERT(
m_bs.GetN() > 0);
488 NS_ASSERT(
m_ut.GetN() > 0);
489 NS_ASSERT_MSG(percentage >= 0 || percentage <= 1,
490 "Percentage must between 0"
493 MobilityHelper mobility;
494 MobilityHelper ueMobility;
495 Ptr<ListPositionAllocator> bsPosVector = CreateObject<ListPositionAllocator>();
496 Ptr<ListPositionAllocator> bsCenterVector = CreateObject<ListPositionAllocator>();
497 Ptr<ListPositionAllocator> sitePosVector = CreateObject<ListPositionAllocator>();
498 Ptr<ListPositionAllocator> utPosVector = CreateObject<ListPositionAllocator>();
501 for (std::size_t cellId = 0; cellId <
m_numBs; cellId++)
504 Vector sitePos(m_centralPos);
505 const double dist = siteDistances.at(siteIndex);
506 const double angleRad = siteAngles.at(siteIndex) * M_PI / 180;
507 sitePos.x +=
m_isd * dist * cos(angleRad);
508 sitePos.y +=
m_isd * dist * sin(angleRad);
513 sitePosVector->Add(sitePos);
520 bsPosVector->Add(bsPos);
524 bsCenterVector->Add(cellCenterPos);
541 m_r->SetAttribute(
"Min", DoubleValue(0));
542 m_r->SetAttribute(
"Max", DoubleValue(outerR * outerR));
543 m_theta->SetAttribute(
"Min", DoubleValue(-1.0 * M_PI));
544 m_theta->SetAttribute(
"Max", DoubleValue(M_PI));
548 uint32_t numUesWithRandomUtHeight = 0;
551 numUesWithRandomUtHeight = percentage *
m_ut.GetN();
554 for (uint32_t utId = 0; utId <
m_ut.GetN(); ++utId)
556 Vector cellCenterPos = bsCenterVector->GetNext();
559 Vector closestSitePosition = GetClosestSitePosition(cellCenterPos, sitePosVector);
561 double distance2DToClosestSite = 0;
567 uint16_t sanityCounter = 0;
570 NS_ABORT_MSG_IF(sanityCounter++ > 1000,
571 "Algorithm needs too many trials to find correct UE position. Please "
572 "check parameters.");
573 double d = std::sqrt(m_r->GetValue());
574 double t = m_theta->GetValue();
575 utPos = cellCenterPos;
576 utPos.x += d * cos(t);
577 utPos.y += d * sin(t);
578 double d_x = utPos.x - closestSitePosition.x;
579 double d_y = utPos.y - closestSitePosition.y;
580 distance2DToClosestSite = sqrt(d_x * d_x + d_y * d_y);
581 }
while (distance2DToClosestSite > m_maxUeDistanceToClosestSite);
583 if (numUesWithRandomUtHeight > 0)
585 Ptr<UniformRandomVariable> uniformRandomVariable =
586 CreateObject<UniformRandomVariable>();
587 double Nfl = uniformRandomVariable->GetValue(4, 8);
588 double nfl = uniformRandomVariable->GetValue(1, Nfl);
592 utPos.z = std::min(3 * (nfl - 1) + 1.5, 9.99);
596 utPos.z = 3 * (nfl - 1) + 1.5;
599 numUesWithRandomUtHeight--;
606 utPosVector->Add(utPos);
609 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
610 mobility.SetPositionAllocator(bsPosVector);
611 mobility.Install(
m_bs);
613 if (speed.GetLength())
615 ueMobility.SetMobilityModel(
"ns3::ConstantVelocityMobilityModel");
616 ueMobility.SetPositionAllocator(utPosVector);
617 ueMobility.Install(
m_ut);
619 for (uint32_t i = 0; i <
m_ut.GetN(); i++)
621 m_ut.Get(i)->GetObject<ConstantVelocityMobilityModel>()->SetVelocity(speed);
626 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
627 mobility.SetPositionAllocator(utPosVector);
628 mobility.Install(
m_ut);
631 PlotHexagonalDeployment(sitePosVector,
642 m_r->SetStream(stream);
643 m_theta->SetStream(stream + 1);
648HexagonalGridScenarioHelper::SetMaxUeDistanceToClosestSite(
double maxUeDistanceToClosestSite)
651 m_maxUeDistanceToClosestSite = maxUeDistanceToClosestSite;
Vector GetHexagonalCellCenter(const Vector &sitePos, uint16_t cellId) const
Returns the cell center coordinates.
int64_t AssignStreams(int64_t stream)
void CreateScenario() override
Create the scenario, with the configured parameter.
~HexagonalGridScenarioHelper() override
~HexagonalGridScenarioHelper
double GetHexagonalCellRadius() const
Gets the radius of the hexagonal cell.
void SetNumRings(uint8_t numRings)
Sets the number of outer rings of sites around the central site.
void CreateScenarioWithMobility(const Vector &speed, double percentage)
This function can be used to create a scenario with UEs with mobility and define a percentage of UEs,...
HexagonalGridScenarioHelper()
HexagonalGridScenarioHelper.
std::size_t m_numBs
Number of base stations to create.
uint16_t GetSiteIndex(std::size_t cellId) const
Gets the site index the queried cell id belongs to.
Vector GetAntennaPosition(const Vector &sitePos, uint16_t cellId) const
Returns the position of the cell antenna.
NodeContainer m_ut
User Terminals.
std::size_t m_numUt
Number of user terminals to create.
std::size_t m_numSites
Number of sites with base stations.
void SetSitesNumber(std::size_t n)
Set number of sites/towers.
NodeContainer m_bs
Base stations.
uint16_t GetSectorIndex(std::size_t cellId) const
Get the sector index the queried cell id belongs to.
double m_isd
Inter-site distance (ISD) in meters.
uint32_t GetNumSectorsPerSite() const
Gets the number of sectors per site.
double m_bsHeight
Height of gNB nodes.
double m_minBsUtDistance
Minimum distance between BS and UT in meters.
double m_utHeight
Height of UE nodes.