5G-LENA nr-v4.0
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-realistic-beamforming.cc
1// Copyright (c) 2020 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#include "ns3/antenna-module.h"
6#include "ns3/applications-module.h"
7#include "ns3/config-store-module.h"
8#include "ns3/core-module.h"
9#include "ns3/internet-module.h"
10#include "ns3/mobility-module.h"
11#include "ns3/nr-module.h"
12#include "ns3/point-to-point-helper.h"
13#include "ns3/sqlite-output.h"
14#include "ns3/stats-module.h"
15
16const uint32_t DB_ATTEMPT_LIMIT = 20; // how many times to try to perform DB query before giving up,
17 // we dont want to enter to a infinite loop
18
19using namespace ns3;
20
89NS_LOG_COMPONENT_DEFINE("CttcRealisticBeamforming");
90
94class CttcRealisticBeamforming
95{
96 public:
97 enum BeamformingMethod
98 {
99 IDEAL,
100 REALISTIC,
101 };
102
111 void UeReception(RxPacketTraceParams params);
112
134 void Configure(double deltaX,
135 double deltaY,
136 BeamformingMethod beamforming,
137 RealisticBfManager::TriggerEvent realTriggerEvent,
138 uint32_t idealPeriodicity,
139 uint64_t rngRun,
140 uint16_t numerology,
141 std::string gnbAntenna,
142 std::string ueAntenna,
143 std::string scenario,
144 double uePower,
145 std::string resultsDirPath,
146 std::string tag,
147 std::string dbName,
148 std::string tableName,
149 std::string condition);
150
156 void RunSimulation();
161 ~CttcRealisticBeamforming();
167 std::string BuildTag();
172 void PrepareOutputFiles();
177 void PrintResultsToFiles();
182 void CreateDlTrafficApplications(ApplicationContainer& serverAppDl,
183 ApplicationContainer& clientAppDl,
184 NodeContainer& ueNode,
185 Ptr<Node> remoteHost,
186 NetDeviceContainer ueNetDev,
187 Ipv4InterfaceContainer& ueIpIface);
188
213 void PrepareDatabase();
214
218 void PrintResultsToDatabase();
219
223 void DeleteFromDatabaseIfAlreadyExist();
224
225 private:
226 // output file streams
227 std::ofstream m_outSinrFile;
228
229 // database related attributes
230 sqlite3* m_db{nullptr};
231 std::string m_tableName{"results"};
232 std::string m_dbName{"realistic_beamforming.db"};
233
234 // statistics collecting object
235 MinMaxAvgTotalCalculator<double> m_sinrStats;
236
237 // main simulation parameters that is expected that user will change often
238 double m_deltaX{1};
239 double m_deltaY{1};
240 BeamformingMethod m_beamforming{IDEAL};
241 uint32_t m_rngRun{1};
242 RealisticBfManager::TriggerEvent m_realTriggerEvent{RealisticBfManager::SRS_COUNT};
243 uint32_t m_idealPeriodicity{0}; // ideal beamforming periodicity in the number of milli seconds
244 uint16_t m_numerology{0};
245 std::string m_gnbAntennaModel{"Iso"};
246 std::string m_ueAntennaModel{"Iso"};
247 std::string m_scenario{"UMa"};
248 std::string m_condition{"Default"};
249 std::string m_resultsDirPath{""};
250 std::string m_tag{""};
251 double m_gNbHeight{25};
252 double m_gNbTxPower{35};
253 double m_ueTxPower{23};
254
255 // simulation parameters that are not expected to be changed often by the user
256 Time m_simTime = MilliSeconds(150);
257 Time m_udpAppStartTimeDl = MilliSeconds(100);
258 Time m_udpAppStopTimeDl = MilliSeconds(150);
259 uint32_t m_packetSize = 1000;
260 DataRate m_udpRate = DataRate("1kbps");
261 double m_centralFrequency = 28e9;
262 double m_bandwidth = 100e6;
263 double m_ueHeight = 1.5; // UE antenna height is 1.5 meters
264
265 const uint8_t m_numCcPerBand = 1;
266 double m_gNbX = 0;
267 double m_gNbY = 0;
268};
269
279std::string
280BuildFileNameString(std::string directoryName, std::string filePrefix, std::string tag)
281{
282 std::ostringstream oss;
283 oss << directoryName << "/" << filePrefix << tag;
284 return oss.str();
285}
286
287std::string
288CttcRealisticBeamforming::BuildTag()
289{
290 NS_LOG_FUNCTION(this);
291
292 std::ostringstream oss;
293 std::string algorithm = (m_beamforming == CttcRealisticBeamforming::IDEAL) ? "I" : "R";
294 double distance2D = sqrt(m_deltaX * m_deltaX + m_deltaY * m_deltaY);
295
296 oss << "-" << algorithm << "-d" << distance2D << "-mu" << m_numerology << "-gnb"
297 << m_gnbAntennaModel << "-ue" << m_ueAntennaModel << "-uePow" << m_ueTxPower << "-scenario"
298 << m_scenario;
299
300 return oss.str();
301}
302
303void
304CttcRealisticBeamforming::PrepareOutputFiles()
305{
306 NS_LOG_FUNCTION(this);
307 // If simulation tag is not provided create one, user can provide his own tag through the
308 // command line
309 if (m_tag.empty())
310 {
311 m_tag = BuildTag();
312 }
313 std::string fileSinr = BuildFileNameString(m_resultsDirPath, "sinrs", m_tag);
314
315 m_outSinrFile.open(fileSinr.c_str(), std::ios_base::app);
316 m_outSinrFile.setf(std::ios_base::fixed);
317 NS_ABORT_MSG_IF(!m_outSinrFile.is_open(), "Can't open file " << fileSinr);
318}
319
320void
321CttcRealisticBeamforming::PrepareDatabase()
322{
323 NS_LOG_FUNCTION(this);
324
325 int rc = sqlite3_open((m_resultsDirPath + "/" + m_dbName).c_str(), &m_db);
326 NS_ABORT_MSG_UNLESS(rc == SQLITE_OK, "Failed to open DB");
327
328 std::string cmd = "CREATE TABLE IF NOT EXISTS " + m_tableName +
329 " ("
330 "SINR DOUBLE NOT NULL, "
331 "SINR_DB DOUBLE NOT NULL, "
332 "Distance DOUBLE NOT NULL,"
333 "DeltaX DOUBLE NOT NULL,"
334 "DeltaY DOUBLE NOT NULL,"
335 "BeamformingType TEXT NOT NULL,"
336 "RngRun INTEGER NOT NULL,"
337 "Numerology INTEGER NOT NULL,"
338 "GnbAntenna TEXT NOT NULL,"
339 "UeAntenna TEXT NOT NULL,"
340 "UePower INTEGER NOT NULL,"
341 "Scenario TEXT NOT NULL);";
342
343 sqlite3_stmt* stmt;
344
345 // prepare the statement for creating the table
346 uint32_t attemptCount = 0;
347 do
348 {
349 rc = sqlite3_prepare_v2(m_db, cmd.c_str(), static_cast<int>(cmd.size()), &stmt, nullptr);
350 NS_ABORT_MSG_IF(
351 ++attemptCount == DB_ATTEMPT_LIMIT,
352 "Waiting too much for sqlite3 database to be ready. "
353 "Check if you have the database/table open with another program. "
354 "If yes, close it before running again cttc-realistic-beamforming program.\n\n");
355 } while (rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
356 // check if it went correctly
357 NS_ABORT_MSG_UNLESS(
358 rc == SQLITE_OK || rc == SQLITE_DONE,
359 "Could not prepare correctly the statement for creating the table. Db error:"
360 << sqlite3_errmsg(m_db) << "full command is: \n"
361 << cmd);
362
363 // execute a step operation on a statement until the result is ok or an error
364 attemptCount = 0;
365 do
366 {
367 rc = sqlite3_step(stmt);
368 NS_ABORT_MSG_IF(
369 ++attemptCount == DB_ATTEMPT_LIMIT,
370 "Waiting too much for sqlite3 database to be ready. "
371 "Check if you have the database/table open with another program. "
372 "If yes, close it before running again cttc-realistic-beamforming program.\n\n");
373 } while (rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
374 // check if it went correctly
375 NS_ABORT_MSG_UNLESS(
376 rc == SQLITE_OK || rc == SQLITE_DONE,
377 "Could not correctly execute the statement for creating the table. Db error:"
378 << sqlite3_errmsg(m_db));
379
380 // finalize the statement until the result is ok or an error occurs
381 attemptCount = 0;
382 do
383 {
384 rc = sqlite3_finalize(stmt);
385 NS_ABORT_MSG_IF(
386 ++attemptCount == DB_ATTEMPT_LIMIT,
387 "Waiting too much for sqlite3 database to be ready. "
388 "Check if you have the database/table open with another program. "
389 "If yes, close it before running again cttc-realistic-beamforming program.\n\n");
390 } while (rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
391 // check if it went correctly
392 NS_ABORT_MSG_UNLESS(
393 rc == SQLITE_OK || rc == SQLITE_DONE,
394 "Could not correctly execute the statement for creating the table. Db error:"
395 << sqlite3_errmsg(m_db));
396}
397
398void
399CttcRealisticBeamforming::PrintResultsToDatabase()
400{
401 NS_LOG_FUNCTION(this);
402
403 DeleteFromDatabaseIfAlreadyExist();
404
405 sqlite3_stmt* stmt;
406 std::string cmd =
407 "INSERT INTO " + m_tableName + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
408 std::string beamformingType = (m_beamforming == IDEAL) ? "Ideal" : "Real";
409 int rc;
410 double distance2D = sqrt(m_deltaX * m_deltaX + m_deltaY * m_deltaY);
411
412 // prepare the statement for creating the table
413 uint32_t attemptCount = 0;
414 do
415 {
416 rc = sqlite3_prepare_v2(m_db, cmd.c_str(), static_cast<int>(cmd.size()), &stmt, nullptr);
417 NS_ABORT_MSG_IF(
418 ++attemptCount == DB_ATTEMPT_LIMIT,
419 "Waiting too much for sqlite3 database to be ready. "
420 "Check if you have the database/table open with another program. "
421 "If yes, close it before running again cttc-realistic-beamforming program.\n\n");
422 } while (rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
423 // check if it went correctly
424 NS_ABORT_MSG_UNLESS(rc == SQLITE_OK || rc == SQLITE_DONE,
425 "Could not prepare correctly the insert into the table statement. "
426 " Db error:"
427 << sqlite3_errmsg(m_db) << ". The full command is: \n"
428 << cmd);
429
430 // add all parameters to the command
431 NS_ABORT_UNLESS(sqlite3_bind_double(stmt, 1, m_sinrStats.getMean()) == SQLITE_OK);
432 NS_ABORT_UNLESS(sqlite3_bind_double(stmt, 2, 10.0 * log10(m_sinrStats.getMean())) == SQLITE_OK);
433 NS_ABORT_UNLESS(sqlite3_bind_double(stmt, 3, distance2D) == SQLITE_OK);
434 NS_ABORT_UNLESS(sqlite3_bind_double(stmt, 4, m_deltaX) == SQLITE_OK);
435 NS_ABORT_UNLESS(sqlite3_bind_double(stmt, 5, m_deltaY) == SQLITE_OK);
436 NS_ABORT_UNLESS(sqlite3_bind_text(stmt, 6, beamformingType.c_str(), -1, SQLITE_STATIC) ==
437 SQLITE_OK);
438 NS_ABORT_UNLESS(sqlite3_bind_int(stmt, 7, m_rngRun) == SQLITE_OK);
439 NS_ABORT_UNLESS(sqlite3_bind_int(stmt, 8, m_numerology) == SQLITE_OK);
440 NS_ABORT_UNLESS(sqlite3_bind_text(stmt, 9, m_gnbAntennaModel.c_str(), -1, SQLITE_STATIC) ==
441 SQLITE_OK);
442 NS_ABORT_UNLESS(sqlite3_bind_text(stmt, 10, m_ueAntennaModel.c_str(), -1, SQLITE_STATIC) ==
443 SQLITE_OK);
444 NS_ABORT_UNLESS(sqlite3_bind_int(stmt, 11, m_ueTxPower) == SQLITE_OK);
445 NS_ABORT_UNLESS(sqlite3_bind_text(stmt, 12, m_scenario.c_str(), -1, SQLITE_STATIC) ==
446 SQLITE_OK);
447
448 // finalize the command
449 attemptCount = 0;
450 do
451 {
452 rc = sqlite3_step(stmt);
453 NS_ABORT_MSG_IF(
454 ++attemptCount == DB_ATTEMPT_LIMIT,
455 "Waiting too much for sqlite3 database to be ready. "
456 "Check if you have the database/table open with another program. "
457 "If yes, close it before running again cttc-realistic-beamforming program.\n\n");
458 } while (rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
459 // check if it went correctly
460 NS_ABORT_MSG_UNLESS(
461 rc == SQLITE_OK || rc == SQLITE_DONE,
462 "Could not correctly execute the statement. Db error:" << sqlite3_errmsg(m_db));
463 attemptCount = 0;
464 do
465 {
466 rc = sqlite3_finalize(stmt);
467 NS_ABORT_MSG_IF(
468 ++attemptCount == DB_ATTEMPT_LIMIT,
469 "Waiting too much for sqlite3 database to be ready. "
470 "Check if you have the database/table open with another program. "
471 "If yes, close it before running again cttc-realistic-beamforming program.\n\n");
472 } while (rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
473 NS_ABORT_MSG_UNLESS(
474 rc == SQLITE_OK || rc == SQLITE_DONE,
475 "Could not correctly execute the statement. Db error:" << sqlite3_errmsg(m_db));
476}
477
478void
479CttcRealisticBeamforming::DeleteFromDatabaseIfAlreadyExist()
480{
481 sqlite3_stmt* stmt;
482 std::string cmd = "DELETE FROM \"" + m_tableName +
483 "\" WHERE "
484 "deltaX == ? AND " // 1
485 "deltaY == ? AND " // 2
486 "BeamformingType = ? AND " // 3
487 "RngRun == ? AND " // 4
488 "Numerology == ? AND " // 5
489 "GnbAntenna = ? AND " // 6
490 "UeAntenna = ? AND " // 7
491 "UePower = ? AND " // 8
492 "Scenario = ?;"; // 9
493 int rc;
494
495 // prepare the statement for creating the table
496 uint32_t attemptCount = 0;
497 do
498 {
499 rc = sqlite3_prepare_v2(m_db, cmd.c_str(), static_cast<int>(cmd.size()), &stmt, nullptr);
500 NS_ABORT_MSG_IF(
501 ++attemptCount == DB_ATTEMPT_LIMIT,
502 "Waiting too much for sqlite3 database to be ready. "
503 "Check if you have the database/table open with another program. "
504 "If yes, close it before running again cttc-realistic-beamforming program.\n\n");
505 } while (rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
506 // check if it went correctly
507 NS_ABORT_MSG_UNLESS(rc == SQLITE_OK || rc == SQLITE_DONE,
508 "Could not prepare correctly the delete statement. "
509 " Db error:"
510 << sqlite3_errmsg(m_db) << ". The full command is: \n"
511 << cmd);
512
513 std::string beamformingType = (m_beamforming == IDEAL) ? "Ideal" : "Real";
514 // add all parameters to the command
515 NS_ABORT_UNLESS(sqlite3_bind_double(stmt, 1, m_deltaX) == SQLITE_OK);
516 NS_ABORT_UNLESS(sqlite3_bind_double(stmt, 2, m_deltaY) == SQLITE_OK);
517 NS_ABORT_UNLESS(sqlite3_bind_text(stmt, 3, beamformingType.c_str(), -1, SQLITE_STATIC) ==
518 SQLITE_OK);
519 NS_ABORT_UNLESS(sqlite3_bind_int(stmt, 4, m_rngRun) == SQLITE_OK);
520 NS_ABORT_UNLESS(sqlite3_bind_int(stmt, 5, m_numerology) == SQLITE_OK);
521 NS_ABORT_UNLESS(sqlite3_bind_text(stmt, 6, m_gnbAntennaModel.c_str(), -1, SQLITE_STATIC) ==
522 SQLITE_OK);
523 NS_ABORT_UNLESS(sqlite3_bind_text(stmt, 7, m_ueAntennaModel.c_str(), -1, SQLITE_STATIC) ==
524 SQLITE_OK);
525 NS_ABORT_UNLESS(sqlite3_bind_int(stmt, 8, m_ueTxPower) == SQLITE_OK);
526 NS_ABORT_UNLESS(sqlite3_bind_text(stmt, 9, m_scenario.c_str(), -1, SQLITE_STATIC) == SQLITE_OK);
527
528 // finalize the command
529 attemptCount = 0;
530 do
531 {
532 rc = sqlite3_step(stmt);
533 NS_ABORT_MSG_IF(
534 ++attemptCount == DB_ATTEMPT_LIMIT,
535 "Waiting too much for sqlite3 database to be ready. "
536 "Check if you have the database/table open with another program. "
537 "If yes, close it before running again cttc-realistic-beamforming program.\n\n");
538 } while (rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
539 // check if it went correctly
540 NS_ABORT_MSG_UNLESS(
541 rc == SQLITE_OK || rc == SQLITE_DONE,
542 "Could not correctly execute the statement. Db error:" << sqlite3_errmsg(m_db));
543 attemptCount = 0;
544 do
545 {
546 rc = sqlite3_finalize(stmt);
547 NS_ABORT_MSG_IF(
548 ++attemptCount == DB_ATTEMPT_LIMIT,
549 "Waiting too much for sqlite3 database to be ready. "
550 "Check if you have the database/table open with another program. "
551 "If yes, close it before running again cttc-realistic-beamforming program.\n\n");
552 } while (rc == SQLITE_BUSY || rc == SQLITE_LOCKED);
553 NS_ABORT_MSG_UNLESS(
554 rc == SQLITE_OK || rc == SQLITE_DONE,
555 "Could not correctly execute the statement. Db error:" << sqlite3_errmsg(m_db));
556}
557
558void
559CttcRealisticBeamforming::CreateDlTrafficApplications(ApplicationContainer& serverAppDl,
560 ApplicationContainer& clientAppDl,
561 NodeContainer& ueNode,
562 Ptr<Node> remoteHost,
563 NetDeviceContainer ueNetDev,
564 Ipv4InterfaceContainer& ueIpIface)
565{
566 NS_LOG_FUNCTION(this);
567 uint16_t dlPort = 1234;
568 // Calculate UDP interval based on the packetSize and desired udp rate
569 Time udpInterval =
570 Time::FromDouble((m_packetSize * 8) / static_cast<double>(m_udpRate.GetBitRate()), Time::S);
571 UdpServerHelper dlPacketSinkHelper(dlPort);
572 serverAppDl.Add(dlPacketSinkHelper.Install(ueNode));
573 // Configure UDP downlink traffic
574 for (uint32_t i = 0; i < ueNetDev.GetN(); i++)
575 {
576 UdpClientHelper dlClient(ueIpIface.GetAddress(i), dlPort);
577 dlClient.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF));
578 dlClient.SetAttribute("PacketSize", UintegerValue(m_packetSize));
579 dlClient.SetAttribute(
580 "Interval",
581 TimeValue(udpInterval)); // we try to saturate, we just need to measure during a short
582 // time, how much traffic can handle each BWP
583 clientAppDl.Add(dlClient.Install(remoteHost));
584 }
585
586 // Start UDP server and client app, and configure stop time
587 serverAppDl.Start(m_udpAppStartTimeDl);
588 clientAppDl.Start(m_udpAppStartTimeDl);
589 serverAppDl.Stop(m_udpAppStopTimeDl);
590 clientAppDl.Stop(m_udpAppStopTimeDl);
591}
592
598void
599UeReceptionTrace(CttcRealisticBeamforming* simSetup, RxPacketTraceParams params)
600{
601 simSetup->UeReception(params);
602}
603
604void
605CttcRealisticBeamforming::UeReception(RxPacketTraceParams params)
606{
607 m_sinrStats.Update(params.m_sinr); // we have to pass the linear value
608}
609
610CttcRealisticBeamforming::~CttcRealisticBeamforming()
611{
612 // close the output results file
613 m_outSinrFile.close();
614
615 // Failed to close the database
616 int rc = SQLITE_FAIL;
617 rc = sqlite3_close_v2(m_db);
618 NS_ABORT_MSG_UNLESS(rc == SQLITE_OK, "Failed to close DB");
619}
620
621void
622CttcRealisticBeamforming::PrintResultsToFiles()
623{
624 NS_LOG_FUNCTION(this);
625 m_outSinrFile << m_sinrStats.getMean() << std::endl;
626}
627
628void
629CttcRealisticBeamforming::Configure(double deltaX,
630 double deltaY,
631 BeamformingMethod beamforming,
632 RealisticBfManager::TriggerEvent realTriggerEvent,
633 uint32_t idealPeriodicity,
634 uint64_t rngRun,
635 uint16_t numerology,
636 std::string gNbAntennaModel,
637 std::string ueAntennaModel,
638 std::string scenario,
639 double uePower,
640 std::string resultsDirPath,
641 std::string tag,
642 std::string dbName,
643 std::string tableName,
644 std::string condition)
645
646{
647 NS_LOG_FUNCTION(this);
648 m_deltaX = deltaX;
649 m_deltaY = deltaY;
650 m_beamforming = beamforming;
651 m_rngRun = rngRun;
652 m_realTriggerEvent = realTriggerEvent;
653 m_idealPeriodicity = idealPeriodicity;
654 m_numerology = numerology;
655 m_gnbAntennaModel = gNbAntennaModel;
656 m_ueAntennaModel = ueAntennaModel;
657 m_scenario = scenario;
658 m_ueTxPower = uePower;
659 m_resultsDirPath = resultsDirPath;
660 m_tag = tag;
661 m_condition = condition;
662 if (scenario == "UMa") // parameters based on TR 38.901 full calibration for RMa, UMa, UMi and
663 // InH-OfficeOpen, 30GHz band
664 {
665 m_gNbHeight = 25; // gNB antenna height
666 m_gNbTxPower = 35; // gNB transmit power
667 }
668 else if (scenario == "RMa")
669 {
670 m_gNbHeight = 35;
671 m_gNbTxPower = 35;
672 }
673 else if (scenario == "UMi")
674 {
675 m_gNbHeight = 10;
676 m_gNbTxPower = 35;
677 }
678 else if (scenario == "InH-OfficeOpen")
679 {
680 m_gNbHeight = 3;
681 m_gNbTxPower = 24;
682 }
683 else
684 {
685 NS_ABORT_MSG("Not supported scenario:" << scenario);
686 }
687}
688
689void
690CttcRealisticBeamforming::RunSimulation()
691{
692 NS_LOG_FUNCTION(this);
693
694 // Set simulation run number
695 SeedManager::SetRun(m_rngRun);
696
697 // Create gNB and UE nodes
698 NodeContainer gNbNode;
699 NodeContainer ueNode;
700 gNbNode.Create(1);
701 ueNode.Create(1);
702
703 // Set positions
704 Ptr<ListPositionAllocator> positions = CreateObject<ListPositionAllocator>();
705 positions->Add(Vector(m_gNbX, m_gNbY, m_gNbHeight)); // gNb will take this position
706 positions->Add(
707 Vector(m_gNbX + m_deltaX, m_gNbY + m_deltaY, m_ueHeight)); // UE will take this position
708 MobilityHelper mobility;
709 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
710 mobility.SetPositionAllocator(positions);
711 mobility.Install(gNbNode);
712 mobility.Install(ueNode);
713
714 // Create NR helpers: nr helper, epc helper, and beamforming helper
715 Ptr<NrHelper> nrHelper = CreateObject<NrHelper>();
716 Ptr<NrPointToPointEpcHelper> nrEpcHelper = CreateObject<NrPointToPointEpcHelper>();
717
718 // Initialize beamforming
719 Ptr<BeamformingHelperBase> beamformingHelper;
720 if (m_beamforming == CttcRealisticBeamforming::IDEAL)
721 {
722 beamformingHelper = CreateObject<IdealBeamformingHelper>();
723 beamformingHelper->SetAttribute("BeamformingPeriodicity",
724 TimeValue(MilliSeconds(m_idealPeriodicity)));
725 beamformingHelper->SetBeamformingMethod(CellScanBeamforming::GetTypeId());
726 }
727 else if (m_beamforming == CttcRealisticBeamforming::REALISTIC)
728 {
729 beamformingHelper = CreateObject<RealisticBeamformingHelper>();
730 beamformingHelper->SetBeamformingMethod(RealisticBeamformingAlgorithm::GetTypeId());
731 // when realistic beamforming used, also realistic beam manager should be set
732 // TODO, move this to NrHelper, so user sets BeamformingMethod calling NrHelper
733 nrHelper->SetGnbBeamManagerTypeId(RealisticBfManager::GetTypeId());
734 nrHelper->SetGnbBeamManagerAttribute("TriggerEvent", EnumValue(m_realTriggerEvent));
735 }
736 else
737 {
738 NS_ABORT_MSG("Unknown beamforming type.");
739 }
740 nrHelper->SetBeamformingHelper(beamformingHelper);
741 nrHelper->SetEpcHelper(nrEpcHelper);
742
743 Config::SetDefault("ns3::NrUePhy::EnableUplinkPowerControl", BooleanValue(false));
744
745 /*
746 * Configure the spectrum division: single operational band, containing single
747 * component carrier, which contains a single bandwidth part.
748 *
749 * |------------------------Band-------------------------|
750 * |-------------------------CC--------------------------|
751 * |-------------------------BWP-------------------------|
752 *
753 */
754 CcBwpCreator ccBwpCreator;
755 // Create the configuration for the CcBwpHelper. SimpleOperationBandConf creates a single BWP
756 // per CC
757 CcBwpCreator::SimpleOperationBandConf bandConf(m_centralFrequency, m_bandwidth, m_numCcPerBand);
758 // By using the configuration created, make the operation band
759 OperationBandInfo band = ccBwpCreator.CreateOperationBandContiguousCc(bandConf);
760 // Initialize spectrum channel
761 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
762 channelHelper->ConfigureFactories(m_scenario, m_condition);
763 // Create and set the channel
764 channelHelper->AssignChannelsToBands({band});
766
767 // Configure antenna of gNb
768 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(4));
769 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(8));
770 // Antenna element type for gNBs
771 if (m_gnbAntennaModel == "Iso")
772 {
773 nrHelper->SetGnbAntennaAttribute("AntennaElement",
774 PointerValue(CreateObject<IsotropicAntennaModel>()));
775 }
776 else
777 {
778 nrHelper->SetGnbAntennaAttribute("AntennaElement",
779 PointerValue(CreateObject<ThreeGppAntennaModel>()));
780 }
781
782 // Configure antenna of UE
783 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(2));
784 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(4));
785 // Antenna element type for UEs
786 if (m_ueAntennaModel == "Iso")
787 {
788 nrHelper->SetUeAntennaAttribute("AntennaElement",
789 PointerValue(CreateObject<IsotropicAntennaModel>()));
790 }
791 else
792 {
793 nrHelper->SetUeAntennaAttribute("AntennaElement",
794 PointerValue(CreateObject<ThreeGppAntennaModel>()));
795 }
796 // configure schedulers
797 nrHelper->SetSchedulerAttribute("SrsSymbols", UintegerValue(1));
798
799 // Install nr net devices
800 NetDeviceContainer gNbDev = nrHelper->InstallGnbDevice(gNbNode, allBwps);
801 NetDeviceContainer ueNetDev = nrHelper->InstallUeDevice(ueNode, allBwps);
802
803 int64_t randomStream = m_rngRun;
804 randomStream += nrHelper->AssignStreams(gNbDev, randomStream);
805 randomStream += nrHelper->AssignStreams(ueNetDev, randomStream);
806
807 for (uint32_t i = 0; i < gNbDev.GetN(); i++)
808 {
809 nrHelper->GetGnbPhy(gNbDev.Get(i), 0)
810 ->SetAttribute("Numerology", UintegerValue(m_numerology));
811 nrHelper->GetGnbPhy(gNbDev.Get(i), 0)->SetAttribute("TxPower", DoubleValue(m_gNbTxPower));
812 }
813 for (uint32_t j = 0; j < ueNetDev.GetN(); j++)
814 {
815 nrHelper->GetUePhy(ueNetDev.Get(j), 0)->SetAttribute("TxPower", DoubleValue(m_ueTxPower));
816 }
817
818 // Create the internet and install the IP stack on the UEs, get SGW/PGW and create a single
819 auto [remoteHost, remoteHostIpv4Address] =
820 nrEpcHelper->SetupRemoteHost("100Gb/s", 2500, Seconds(0.000));
821 InternetStackHelper internet;
822 internet.Install(ueNode);
823 Ipv4InterfaceContainer ueIpIface;
824 ueIpIface = nrEpcHelper->AssignUeIpv4Address(NetDeviceContainer(ueNetDev));
825
826 // Attach UE to gNB
827 nrHelper->AttachToGnb(ueNetDev.Get(0), gNbDev.Get(0));
828
829 // Install UDP downlink applications
830 ApplicationContainer clientAppDl;
831 ApplicationContainer serverAppDl;
832 CreateDlTrafficApplications(clientAppDl, serverAppDl, ueNode, remoteHost, ueNetDev, ueIpIface);
833
834 // Connect traces to our listener functions
835 for (uint32_t i = 0; i < ueNetDev.GetN(); i++)
836 {
837 Ptr<NrSpectrumPhy> ue1SpectrumPhy =
838 DynamicCast<NrUeNetDevice>(ueNetDev.Get(i))->GetPhy(0)->GetSpectrumPhy();
839 ue1SpectrumPhy->TraceConnectWithoutContext("RxPacketTraceUe",
840 MakeBoundCallback(&UeReceptionTrace, this));
841 Ptr<NrInterference> ue1SpectrumPhyInterference = ue1SpectrumPhy->GetNrInterference();
842 NS_ABORT_IF(!ue1SpectrumPhyInterference);
843 }
844
845 Simulator::Stop(m_simTime);
846 Simulator::Run();
847 Simulator::Destroy();
848}
849
850int
851main(int argc, char* argv[])
852{
853 // simulation configuration parameters
854 double deltaX = 10.0;
855 double deltaY = 10.0;
856 std::string algType = "Real";
857 std::string realTriggerEvent =
858 "SrsCount"; // what will be the trigger event to update the beamforming vectors, only used
859 // when --algType="Real"
860 uint32_t idealPeriodicity = 10; // how often will be updated the beamforming vectors, only used
861 // when --algType="Ideal", in [ms]
862 uint64_t rngRun = 1;
863 uint16_t numerology = 2;
864 std::string gnbAntenna = "Iso";
865 std::string ueAntenna = "Iso";
866 double ueTxPower = 1;
867 std::string scenario = "UMa";
868 std::string condition = "Default";
869 // parameters for saving the output
870 std::string resultsDir = ".";
871 std::string simTag = "";
872 std::string dbName = "realistic-beamforming.db";
873 std::string tableName = "results";
874
875 CttcRealisticBeamforming::BeamformingMethod beamformingType;
876 RealisticBfManager::TriggerEvent triggerEventEnum = RealisticBfManager::SRS_COUNT;
877 CommandLine cmd(__FILE__);
878
879 cmd.AddValue("deltaX",
880 "Determines X coordinate of UE wrt. to gNB X coordinate [meters].",
881 deltaX);
882 cmd.AddValue("deltaY",
883 "Determines Y coordinate of UE wrt. to gNB Y coordinate [meters].",
884 deltaY);
885 cmd.AddValue("algType", "Algorithm type to be used. Can be: 'Ideal' or 'Real'.", algType);
886 cmd.AddValue(
887 "realTriggerEvent",
888 "In the case of the realistic beafmorming (algType=\"Real\") it defines when the "
889 "beamforming "
890 "vectors will be updated: upon each SRS reception but with a certain delay, or after "
891 "certain number of SRSs."
892 "For the first option the parameter should be configured with 'DelayedUpdate' and for the "
893 "second option the value to be configured is 'SrsCount'",
894 realTriggerEvent);
895 cmd.AddValue(
896 "idealPeriodicity",
897 "In the case of the ideal beamforminng (algType=\"Ideal\") it defines how often the "
898 "beamforming vectors will be updated in milli seconds [ms].",
899 idealPeriodicity);
900 cmd.AddValue("rngRun", "Rng run random number.", rngRun);
901 cmd.AddValue("numerology", "Numerology to be used.", numerology);
902 cmd.AddValue("gnbAntenna", "Configure antenna elements at gNb: Iso or 3gpp", gnbAntenna);
903 cmd.AddValue("ueAntenna", "Configure antenna elements at UE: Iso or 3gpp", ueAntenna);
904 cmd.AddValue("scenario", "Deployment scenario: UMa, UMi, InH-OfficeOpen", scenario);
905 cmd.AddValue("condition", "The channel condition: Default, NLOS or LOS", condition);
906 cmd.AddValue("uePower", "Tx power to be used by the UE [dBm].", ueTxPower);
907 // output command line parameters
908 cmd.AddValue("resultsDir", "Directory where to store the simulation results.", resultsDir);
909 cmd.AddValue("simTag",
910 "Tag to be appended to output filenames to distinguish simulation campaigns.",
911 simTag);
912 cmd.AddValue("dbName", "Database name.", dbName);
913 cmd.AddValue("tableName", "Table name.", tableName);
914 cmd.Parse(argc, argv);
915
916 if (algType == "Ideal")
917 {
918 beamformingType = CttcRealisticBeamforming::IDEAL;
919 }
920 else if (algType == "Real")
921 {
922 beamformingType = CttcRealisticBeamforming::REALISTIC;
923
924 if (realTriggerEvent == "SrsCount")
925 {
926 triggerEventEnum = RealisticBfManager::SRS_COUNT;
927 }
928 else if (realTriggerEvent == "DelayedUpdate")
929 {
930 triggerEventEnum = RealisticBfManager::DELAYED_UPDATE;
931 }
932 else
933 {
934 NS_ABORT_MSG(
935 "Not supported trigger event for the realistic type of beamforming:" << algType);
936 }
937 }
938 else
939 {
940 NS_ABORT_MSG("Not supported value for algType:" << algType);
941 }
942
943 CttcRealisticBeamforming simpleBeamformingScenario;
944 simpleBeamformingScenario.Configure(deltaX,
945 deltaY,
946 beamformingType,
947 triggerEventEnum,
948 idealPeriodicity,
949 rngRun,
950 numerology,
951 gnbAntenna,
952 ueAntenna,
953 scenario,
954 ueTxPower,
955 resultsDir,
956 simTag,
957 dbName,
958 tableName,
959 condition);
960 simpleBeamformingScenario.PrepareDatabase();
961 simpleBeamformingScenario.PrepareOutputFiles();
962 simpleBeamformingScenario.RunSimulation();
963 simpleBeamformingScenario.PrintResultsToDatabase();
964 simpleBeamformingScenario.PrintResultsToFiles();
965}
Manages the correct creation of operation bands, component carriers and bandwidth parts.
OperationBandInfo CreateOperationBandContiguousCc(const SimpleOperationBandConf &conf)
Create an operation band with the CC specified.
static BandwidthPartInfoPtrVector GetAllBwps(const std::vector< std::reference_wrapper< OperationBandInfo > > &operationBands)
Get all the BWP pointers from the specified vector of operation bands.
static TypeId GetTypeId()
Get the type id.
static TypeId GetTypeId()
GetTypeId.
std::string BuildFileNameString(std::string directoryName, std::string filePrefix, std::string tag)
std::string BuildTag(bool gNbAntennaModel, bool ueAntennaModel, std::string scenario, double speed)
void UeReceptionTrace(Nr3gppIndoorCalibration *scenario, RxPacketTraceParams params)
std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > BandwidthPartInfoPtrVector
vector of unique_ptr of BandwidthPartInfo
Minimum configuration requirements for a OperationBand.
Operation band information structure.
The RxPacketTraceParams struct.