```cpp= /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Michele Polese <michele.polese@gmail.com> */ #include "ns3/mmwave-helper.h" #include "ns3/epc-helper.h" #include "ns3/node-list.h" #include "ns3/isotropic-antenna-model.h" #include "ns3/internet-module.h" #include "ns3/mobility-module.h" #include "ns3/applications-module.h" #include "ns3/point-to-point-helper.h" #include "ns3/config-store-module.h" #include "ns3/mmwave-point-to-point-epc-helper.h" #include "ns3/buildings-helper.h" #include "ns3/buildings-module.h" #include "ns3/global-value.h" #include "ns3/command-line.h" #include "ns3/basic-energy-source-helper.h" #include "ns3/mmwave-energy-helper.h" #include "ns3/mmwave-radio-energy-model-enb-helper.h" #include <ns3/random-variable-stream.h> #include <ns3/lte-ue-net-device.h> #include<ns3/rng-seed-manager.h> #include <iostream> #include <ctime> #include <stdlib.h> // #include<time.h> #include<random> #include<chrono> #include <list> #include "ns3/netanim-module.h" //new log #include "ns3/log.h" #include "ns3/mmwave-bearer-stats-calculator.h" #include <fstream> #include <sstream> using namespace ns3; using namespace mmwave; /** * Sample simulation script for MC devices. * One LTE and two MmWave eNodeBs are instantiated, and a MC UE device is placed between them. * In particular, the UE is initially closer to one of the two BSs, and progressively moves towards the other. * During the course of the simulation multiple handovers occur, due to the changing distance between the devices * and the presence of obstacles, which can obstruct the LOS path between the UE and the eNBs. */ //****************************************Map to store Position of BSs *************************************************************|| std::map<uint32_t,Vector> Bs_positions; //**********************************************************************************************************************************|| //****************************************Map to store tottal number of UEs connected to particular Base Station********************|| std::map<uint32_t,int> total_UEs_connected; //**********************************************************************************************************************************|| //****************************************Map to store the status(OFF->false/ ON->True) of BaseStation******************************|| std::map<uint32_t,bool> Bs_status; //**********************************************************************************************************************************|| //********************************************Map to store cell id of current BS to which UE is connected***************************|| std::map<uint32_t,uint32_t> current_Bs; //**********************************************************************************************************************************|| int sleeparray[12]; // std::vector<bool> sleeparray; // 假设这是一个表示每个基站睡眠状态的向量。 NodeContainer mmWaveEnbNodes; // static double lastLoggedTime = 0; // Track the last time we logged // static double lastLoggedTime = 0; // Track the last time we logged // MWNL std::ofstream logFile("mmWaveSleepLog.txt", std::ios::app); // Open the log file in append mode NS_LOG_COMPONENT_DEFINE ("McTwoEnbs"); // void NotifyMmWaveTarget (std::string context, uint64_t imsi, uint16_t cellId, long double targetID) { // std::cout << "* " << Simulator::Now().GetSeconds() // << " IMSI " << imsi << " Target " << targetID << "\n"; // } void NotifyMmWaveSleep (std::string context, uint16_t cellId, long double sleep) { logFile << "* " << ns3::Simulator::Now().GetSeconds() << " CellId " << cellId << " sleep mode 0 can't sleep 1 can sleep : " << sleep << "\n"; std::cout << "* " << Simulator::Now().GetSeconds() << " CellId " << cellId << " sleep mode 0 can't sleep 1 can sleep : " << sleep << "\n"; sleeparray[cellId] = sleep; } std::map<uint16_t, long double> sleepState; // void NotifyMmWaveSleep(std::string context, uint16_t cellId, long double sleep) { // static double lastLoggedTime = 0; // Last logged time initialized to 0 // double currentTime = ns3::Simulator::Now().GetSeconds(); // // Calculate the next log time based on the last logged time // double nextLogTime = lastLoggedTime + 0.05; // if (currentTime >= nextLogTime) { // // Record the log // logFile << "* " << currentTime // << " CellId " << cellId << " sleep mode 0 can't sleep 1 can sleep : " << sleep << "\n"; // std::cout << "* " << currentTime // << " CellId " << cellId << " sleep mode 0 can't sleep 1 can sleep : " << sleep << "\n"; // // Update lastLoggedTime to the current log time // lastLoggedTime = nextLogTime; // } // sleeparray[cellId] = sleep; // Update the sleep status // } // void NotifyMmWaveSleep(std::string context, uint16_t cellId, long double sleep) { // static double nextLogTime = 0; // Next scheduled log time // double currentTime = ns3::Simulator::Now().GetSeconds(); // if (currentTime >= nextLogTime) { // Only log and update if current time reached or passed the next scheduled time // logFile << "* " << currentTime // << " CellId " << cellId << " sleep mode 0 can't sleep 1 can sleep : " << sleep << "\n"; // std::cout << "* " << currentTime // << " CellId " << cellId << " sleep mode 0 can't sleep 1 can sleep : " << sleep << "\n"; // lastLoggedTime = currentTime; // Update the last logged time // nextLogTime += 0.05; // Schedule the next log time // } // sleeparray[cellId] = sleep; // } // void NotifyMmWaveSinr (std::string context, uint64_t imsi, uint16_t cellId, long double sinr) { // std::cout << "* " << Simulator::Now().GetSeconds() << " " << context // << " CellId " << cellId << " IMSI " << imsi << " SINR " << sinr << "\n"; // } // void NotifyMmWaveServing (std::string context, uint64_t imsi, uint16_t cellId, long double servingID) { // std::cout << "* " << Simulator::Now().GetSeconds() << " " << context // << " CellId " << cellId << " IMSI " << imsi << " Serving " << servingID << "\n"; // } // MWNL // void PrintSleepTest(){ // for ( int i = 2;i<12 ;i++){ // std::cout << "* " << Simulator::Now().GetSeconds() // << " CELL " << i << " Sleep signal " << sleeparray[i] << "\n"; // } // ns3::Simulator::Schedule(ns3::Seconds(0.05), &PrintSleepTest); // } void PrintGnuplottableBuildingListToFile (std::string filename) { std::ofstream outFile; outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc); if (!outFile.is_open ()) { NS_LOG_ERROR ("Can't open file " << filename); return; } uint32_t index = 0; for (BuildingList::Iterator it = BuildingList::Begin (); it != BuildingList::End (); ++it) { ++index; Box box = (*it)->GetBoundaries (); outFile << "set object " << index << " rect from " << box.xMin << "," << box.yMin << " to " << box.xMax << "," << box.yMax << " front fs empty " << std::endl; } } void PrintGnuplottableUeListToFile (std::string filename) { std::ofstream outFile; outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc); if (!outFile.is_open ()) { NS_LOG_ERROR ("Can't open file " << filename); return; } for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it) { Ptr<Node> node = *it; int nDevs = node->GetNDevices (); for (int j = 0; j < nDevs; j++) { Ptr<LteUeNetDevice> uedev = node->GetDevice (j)->GetObject <LteUeNetDevice> (); Ptr<MmWaveUeNetDevice> mmuedev = node->GetDevice (j)->GetObject <MmWaveUeNetDevice> (); Ptr<McUeNetDevice> mcuedev = node->GetDevice (j)->GetObject <McUeNetDevice> (); if (uedev) { Vector pos = node->GetObject<MobilityModel> ()->GetPosition (); outFile << "set label \"" << uedev->GetImsi () << "\" at " << pos.x << "," << pos.y << " left font \"Helvetica,8\" textcolor rgb \"black\" front point pt 1 ps 0.3 lc rgb \"black\" offset 0,0" << std::endl; } else if (mmuedev) { Vector pos = node->GetObject<MobilityModel> ()->GetPosition (); outFile << "set label \"" << mmuedev->GetImsi () << "\" at " << pos.x << "," << pos.y << " left font \"Helvetica,8\" textcolor rgb \"black\" front point pt 1 ps 0.3 lc rgb \"black\" offset 0,0" << std::endl; } else if (mcuedev) { Vector pos = node->GetObject<MobilityModel> ()->GetPosition (); outFile << "set label \"" << mcuedev->GetImsi () << "\" at " << pos.x << "," << pos.y << " left font \"Helvetica,8\" textcolor rgb \"black\" front point pt 1 ps 0.3 lc rgb \"black\" offset 0,0" << std::endl; } } } } void PrintGnuplottableEnbListToFile (std::string filename) { std::ofstream outFile; outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc); if (!outFile.is_open ()) { NS_LOG_ERROR ("Can't open file " << filename); return; } for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it) { Ptr<Node> node = *it; int nDevs = node->GetNDevices (); for (int j = 0; j < nDevs; j++) { Ptr<LteEnbNetDevice> enbdev = node->GetDevice (j)->GetObject <LteEnbNetDevice> (); Ptr<MmWaveEnbNetDevice> mmdev = node->GetDevice (j)->GetObject <MmWaveEnbNetDevice> (); if (enbdev) { Vector pos = node->GetObject<MobilityModel> ()->GetPosition (); outFile << "set label \"" << enbdev->GetCellId () << "\" at " << pos.x << "," << pos.y << " left font \"Helvetica,8\" textcolor rgb \"blue\" front point pt 4 ps 0.3 lc rgb \"blue\" offset 0,0" << std::endl; } else if (mmdev) { Vector pos = node->GetObject<MobilityModel> ()->GetPosition (); outFile << "set label \"" << mmdev->GetCellId () << "\" at " << pos.x << "," << pos.y << " left font \"Helvetica,8\" textcolor rgb \"red\" front point pt 4 ps 0.3 lc rgb \"red\" offset 0,0" << std::endl; } } } } void ChangePosition (Ptr<Node> node, Vector vector) { Ptr<MobilityModel> model = node->GetObject<MobilityModel> (); model->SetPosition (vector); NS_LOG_UNCOND ("************************--------------------Change Position-------------------------------*****************"); } void ChangeSpeed (Ptr<Node> n, Vector speed) { n->GetObject<ConstantVelocityMobilityModel> ()->SetVelocity (speed); NS_LOG_UNCOND ("************************--------------------Change Speed-------------------------------*****************"); } void PrintPosition (Ptr<Node> node) { Ptr<MobilityModel> model = node->GetObject<MobilityModel> (); NS_LOG_UNCOND ("Position +****************************** " << model->GetPosition () << " at time " << Simulator::Now ().GetSeconds ()); } void PrintLostUdpPackets (Ptr<UdpServer> app, std::string fileName) { std::ofstream logFile (fileName.c_str (), std::ofstream::app); logFile << Simulator::Now ().GetSeconds () << " " << app->GetLost () << std::endl; logFile.close (); Simulator::Schedule (MilliSeconds (20), &PrintLostUdpPackets, app, fileName); } bool AreOverlapping (Box a, Box b) { return !((a.xMin > b.xMax) || (b.xMin > a.xMax) || (a.yMin > b.yMax) || (b.yMin > a.yMax) ); } bool OverlapWithAnyPrevious (Box box, std::list<Box> m_previousBlocks) { for (std::list<Box>::iterator it = m_previousBlocks.begin (); it != m_previousBlocks.end (); ++it) { if (AreOverlapping (*it,box)) { return true; } } return false; } std::pair<Box, std::list<Box> > GenerateBuildingBounds (double xArea, double yArea, double maxBuildSize, std::list<Box> m_previousBlocks ) { Ptr<UniformRandomVariable> xMinBuilding = CreateObject<UniformRandomVariable> (); xMinBuilding->SetAttribute ("Min",DoubleValue (30)); xMinBuilding->SetAttribute ("Max",DoubleValue (xArea)); NS_LOG_UNCOND ("min " << 0 << " max " << xArea); Ptr<UniformRandomVariable> yMinBuilding = CreateObject<UniformRandomVariable> (); yMinBuilding->SetAttribute ("Min",DoubleValue (0)); yMinBuilding->SetAttribute ("Max",DoubleValue (yArea)); NS_LOG_UNCOND ("min " << 0 << " max " << yArea); Box box; uint32_t attempt = 0; do { NS_ASSERT_MSG (attempt < 100, "Too many failed attempts to position non-overlapping buildings. Maybe area too small or too many buildings?"); box.xMin = xMinBuilding->GetValue (); Ptr<UniformRandomVariable> xMaxBuilding = CreateObject<UniformRandomVariable> (); xMaxBuilding->SetAttribute ("Min",DoubleValue (box.xMin)); xMaxBuilding->SetAttribute ("Max",DoubleValue (box.xMin + maxBuildSize)); box.xMax = xMaxBuilding->GetValue (); box.yMin = yMinBuilding->GetValue (); Ptr<UniformRandomVariable> yMaxBuilding = CreateObject<UniformRandomVariable> (); yMaxBuilding->SetAttribute ("Min",DoubleValue (box.yMin)); yMaxBuilding->SetAttribute ("Max",DoubleValue (box.yMin + maxBuildSize)); box.yMax = yMaxBuilding->GetValue (); ++attempt; } while (OverlapWithAnyPrevious (box, m_previousBlocks)); NS_LOG_UNCOND ("Building in coordinates (" << box.xMin << " , " << box.yMin << ") and (" << box.xMax << " , " << box.yMax << ") accepted after " << attempt << " attempts"); m_previousBlocks.push_back (box); std::pair<Box, std::list<Box> > pairReturn = std::make_pair (box,m_previousBlocks); return pairReturn; } static ns3::GlobalValue g_mmw1DistFromMainStreet ("mmw1Dist", "Distance from the main street of the first MmWaveEnb", ns3::UintegerValue (50), ns3::MakeUintegerChecker<uint32_t> ()); static ns3::GlobalValue g_mmw2DistFromMainStreet ("mmw2Dist", "Distance from the main street of the second MmWaveEnb", ns3::UintegerValue (50), ns3::MakeUintegerChecker<uint32_t> ()); static ns3::GlobalValue g_mmw3DistFromMainStreet ("mmw3Dist", "Distance from the main street of the third MmWaveEnb", ns3::UintegerValue (110), ns3::MakeUintegerChecker<uint32_t> ()); static ns3::GlobalValue g_mmWaveDistance ("mmWaveDist", "Distance between MmWave eNB 1 and 2", ns3::UintegerValue (200), ns3::MakeUintegerChecker<uint32_t> ()); static ns3::GlobalValue g_numBuildingsBetweenMmWaveEnb ("numBlocks", "Number of buildings between MmWave eNB 1 and 2", ns3::UintegerValue (8), ns3::MakeUintegerChecker<uint32_t> ()); static ns3::GlobalValue g_interPckInterval ("interPckInterval", "Interarrival time of UDP packets (us)", ns3::UintegerValue (20), ns3::MakeUintegerChecker<uint32_t> ()); static ns3::GlobalValue g_bufferSize ("bufferSize", "RLC tx buffer size (MB)", ns3::UintegerValue (20), ns3::MakeUintegerChecker<uint32_t> ()); static ns3::GlobalValue g_x2Latency ("x2Latency", "Latency on X2 interface (us)", ns3::DoubleValue (500), ns3::MakeDoubleChecker<double> ()); static ns3::GlobalValue g_mmeLatency ("mmeLatency", "Latency on MME interface (us)", ns3::DoubleValue (10000), ns3::MakeDoubleChecker<double> ()); static ns3::GlobalValue g_mobileUeSpeed ("mobileSpeed", "The speed of the UE (m/s)", ns3::DoubleValue (2), ns3::MakeDoubleChecker<double> ()); static ns3::GlobalValue g_rlcAmEnabled ("rlcAmEnabled", "If true, use RLC AM, else use RLC UM", ns3::BooleanValue (true), ns3::MakeBooleanChecker ()); static ns3::GlobalValue g_maxXAxis ("maxXAxis", "The maximum X coordinate for the area in which to deploy the buildings", ns3::DoubleValue (150), ns3::MakeDoubleChecker<double> ()); static ns3::GlobalValue g_maxYAxis ("maxYAxis", "The maximum Y coordinate for the area in which to deploy the buildings", ns3::DoubleValue (40), ns3::MakeDoubleChecker<double> ()); static ns3::GlobalValue g_outPath ("outPath", "The path of output log files", ns3::StringValue ("./"), ns3::MakeStringChecker ()); static ns3::GlobalValue g_noiseAndFilter ("noiseAndFilter", "If true, use noisy SINR samples, filtered. If false, just use the SINR measure", ns3::BooleanValue (false), ns3::MakeBooleanChecker ()); static ns3::GlobalValue g_handoverMode ("handoverMode", "Handover mode", ns3::UintegerValue (3), ns3::MakeUintegerChecker<uint8_t> ()); static ns3::GlobalValue g_reportTablePeriodicity ("reportTablePeriodicity", "Periodicity of RTs", ns3::UintegerValue (1600), ns3::MakeUintegerChecker<uint32_t> ()); static ns3::GlobalValue g_outageThreshold ("outageTh", "Outage threshold", ns3::DoubleValue (-5), ns3::MakeDoubleChecker<double> ()); static ns3::GlobalValue g_lteUplink ("lteUplink", "If true, always use LTE for uplink signalling", ns3::BooleanValue (false), ns3::MakeBooleanChecker ()); void MakeBaseStationSleep (Ptr<MmWaveSpectrumPhy> endlphy, Ptr<MmWaveSpectrumPhy> enulphy, bool val,uint16_t cellid) { // val == 1 means sleep double currenttime = Simulator::Now ().GetSeconds (); if (val == 1) { std::cout << cellid << ", Base Station going to sleep at time " << currenttime << "\n"; } else { std::cout << cellid << ", Base Station awakened at time " << currenttime << "\n"; } // std::cout << cellid << ", Base Station change state at time ," << currenttime << ", Sleep: " << val << "\n"; endlphy->SetAttribute ("MakeItSleep", BooleanValue(val)); enulphy->SetAttribute ("MakeItSleep", BooleanValue(val)); } void EnergyConsumptionUpdate(uint32_t u_id, double totaloldEnergyConsumption, double totalnewEnergyConsumption) { // std::cout << "UE Node " << u << ", " << totaloldEnergyConsumption << ", " << totalnewEnergyConsumption << std::endl; std::ofstream log_file_ue; log_file_ue.open("log_file_ue_pos_handover_energy_consumption.txt",std::ios::out | std::ios::app); log_file_ue << "UE Power," <<Simulator::Now().GetSeconds()<< u_id<<","<<totaloldEnergyConsumption << "," << totalnewEnergyConsumption <<std::endl; log_file_ue.close(); // file } void EnergyConsumptionUpdateBS(uint32_t b_id, double totaloldEnergyConsumption, double totalnewEnergyConsumption) { // std::cout << "Base Station Node " << u << ", " << totaloldEnergyConsumption << ", " << totalnewEnergyConsumption << std::endl; std::ofstream log_file_bs; // convert now to string form // std::string date_time = ctime(&now); log_file_bs.open("log_file_bs_ue_pos_handover_energy_consumption.txt",std::ios::out | std::ios::app); log_file_bs << "Base Station Power," << Simulator::Now().GetSeconds()<<","<<b_id<<","<< totaloldEnergyConsumption << "," << totalnewEnergyConsumption << std::endl; log_file_bs.close(); } /****************************************************************MY_FUNCTIONS******************************************************/ /* ||***********************************Assigning_Random_Position_to_GNBs**********************************|| || deployEnb function takes a 2D matrix as input of sz size rows and two columns || sz -> number of gNB nodes. || populates this matrix with some random x , y position with in some bounded conditions. ||******************************************************************************************************|| */ void deployEnb (int deploypoints[][2],int sz) { unsigned seed1 = std::chrono::system_clock::now ().time_since_epoch ().count (); std::default_random_engine generator (seed1); std::uniform_int_distribution<int> distribution (1, 1000); int x = distribution (generator); int y = distribution (generator); std::cout << "1 Point X: " << x << "\tY: " << y << std::endl; deploypoints[0][0] = x; deploypoints[0][1] = y; int numofgNb = 1; int intergNbgap = 100; int numofAttempts = 0; while (numofgNb < 10) { numofAttempts++; int thisx = distribution (generator); int thisy = distribution (generator); bool overlapping = false; for (int j = 0; j < numofgNb; j++) { double distance = sqrt ( (pow ((thisx - deploypoints[j][0]), 2) + pow ((thisy - deploypoints[j][1]), 2))); if ((distance < 2 * intergNbgap) || (thisx < 150) || (thisy < 150) || (thisx > 850) || (thisy > 850)) { //overlapping gNbs overlapping = true; break; } } if (!overlapping) { deploypoints[numofgNb][0] = thisx; deploypoints[numofgNb][1] = thisy; numofgNb++; std::cout << numofgNb << " Point X: " << deploypoints[numofgNb - 1][0] << "\tY: " << deploypoints[numofgNb - 1][1] << std::endl; } if (numofAttempts > 10000) { break; } } std::cout << "Number of Attempts Made\t" << numofAttempts << std::endl; } //************************************************End of deployEnb**********************************|| // //*****************************************Make_Base_Station_Sleep*********************************|| // void SwitchOffIdleBaseStation(Vector UE_pos , int u_id , Ptr<const MobilityModel> model) // { // // Vector UEpos = ueNodes.Get(u_id)->GetObject<MobilityModel> ()->GetPosition (); // uint32_t nearest_bs_id = current_Bs[u_id]; // Vector naerest_bs_pos = mmWaveEnbNodes.Get(0)->GetObject<MobilityModel>()->GetPosition(); // for(auto j : Bs_positions) // { // if(j.first == 0) // continue; // Vector bs_pos = j.second; // if(pow(UE_pos.x-bs_pos.x,2)+pow(UE_pos.y-bs_pos.y,2) < pow(UE_pos.x - naerest_bs_pos.x,2)+pow(UE_pos.y-naerest_bs_pos.y,2)) // { // naerest_bs_pos = bs_pos; // nearest_bs_id = j.first; // } // } // if(current_Bs[u_id] != nearest_bs_id) // { // total_UEs_connected[current_Bs[u_id]]--; // if(total_UEs_connected[current_Bs[u_id]] == 0) // { // // switchoffcurrent_Bs[u_id]; // Ptr<MmWaveEnbPhy> enbPhy = mmWaveEnbNodes.Get(current_Bs[u_id])->GetDevice(0)->GetObject<MmWaveEnbNetDevice> ()->GetPhy (); // Ptr<MmWaveSpectrumPhy> enbdl= enbPhy->GetDlSpectrumPhy (); // Ptr<MmWaveSpectrumPhy> enbul= enbPhy->GetUlSpectrumPhy (); // Simulator::Schedule(Seconds(Simulator::Now().GetSeconds()), &MakeBaseStationSleep, enbdl, enbul,true,current_Bs[u_id]);//have to change // Bs_status[current_Bs[u_id]] = false; // } // if(Bs_status[nearest_bs_id] == false) // { // //SwitchOnNearestBsId; // Ptr<MmWaveEnbPhy> enbPhy = mmWaveEnbNodes.Get(current_Bs[u_id])->GetDevice(0)->GetObject<MmWaveEnbNetDevice> ()->GetPhy (); // Ptr<MmWaveSpectrumPhy> enbdl= enbPhy->GetDlSpectrumPhy (); // Ptr<MmWaveSpectrumPhy> enbul= enbPhy->GetUlSpectrumPhy (); // Simulator::Schedule(Seconds(Simulator::Now().GetSeconds()), &MakeBaseStationSleep, enbdl, enbul,false,current_Bs[u_id]);//have to change // Bs_status[nearest_bs_id] = true; // } // total_UEs_connected[nearest_bs_id]++; // } // // current_Bs[i] = nearest_bs_id; // // total_UEs_connected[nearest_bs_id]++; // } // //**************************************************************************************************|| struct UeMovement { bool hasEnteredTargetArea = false; Time entryTime; }; std::map<Ptr<Node>, UeMovement> ueMovements; void LogPosition(Ptr<Node> node, std::string filename) { Ptr<MobilityModel> mobility = node->GetObject<MobilityModel>(); Vector pos = mobility->GetPosition(); // 获取位置 std::ofstream file; file.open(filename, std::ios::app); // 打开文件用于追加 file << Simulator::Now().GetSeconds() << "s: (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl; file.close(); } void ScheduleLogPosition(Ptr<Node> node, std::string filename, double interval) { Simulator::Schedule(Seconds(interval), &ScheduleLogPosition, node, filename, interval); LogPosition(node, filename); } void PrintUEPositions(NodeContainer& ueNodes) { // std::ofstream outFile; // outFile.open("UEPositions.txt"); // Open a file to store the positions for (uint32_t i = 0; i < ueNodes.GetN(); ++i) { Ptr<Node> node = ueNodes.Get(i); Ptr<MobilityModel> mobility = node->GetObject<MobilityModel>(); Vector pos = mobility->GetPosition(); std::cout << "UE " << i << ": Position(" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl; // outFile << "UE " << i << ": Position(" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl; } // outFile.close(); // Close the file after writing } std::ofstream positionLogFile; void UpdatePosition(Ptr<Node> node, Vector velocity, Time downtown_stopTime, Time startTime, bool& isMovingBack, Time& reverseStartTime) { Time now = Simulator::Now(); Ptr<ConstantVelocityMobilityModel> mobility = node->GetObject<ConstantVelocityMobilityModel>(); if (!mobility) return; // 如果沒有移動模型,則直接返回 // 如果到達開始反向移動的時間,且當前不是反向狀態 if (now >= startTime && !isMovingBack) { velocity.x = -velocity.x; velocity.y = -velocity.y; isMovingBack = true; reverseStartTime = now; // 設定折返開始的時間 } // 更新位置,如果當前時間小於停止時間或者是反向移動狀態 if (now < downtown_stopTime || isMovingBack) { Vector pos = mobility->GetPosition(); Vector newPos = Vector(pos.x + velocity.x * 0.1, pos.y + velocity.y * 0.1, pos.z); mobility->SetPosition(newPos); } // 無條件調度下一次更新,除非在反向移動0.15秒後 // if (isMovingBack && (now - reverseStartTime) >= Seconds(0.05)) { if (isMovingBack && (now - reverseStartTime) >= Seconds(0.75)) { return; // 如果已經折返0.15秒,則不再調度 } Simulator::Schedule(Seconds(0.005), &UpdatePosition, node, velocity, downtown_stopTime, startTime, isMovingBack, reverseStartTime); } void RecordPositions(NodeContainer &nodes, std::ofstream &logFile) { double timeInSeconds = Simulator::Now().GetSeconds(); for (NodeContainer::Iterator i = nodes.Begin(); i != nodes.End(); ++i) { Ptr<Node> node = *i; Ptr<MobilityModel> mobility = node->GetObject<MobilityModel>(); if (mobility) { Vector pos = mobility->GetPosition(); uint32_t nodeId = node->GetId(); logFile << timeInSeconds << " Node " << nodeId << ": Position: " << pos.x << ", " << pos.y << ", " << pos.z << std::endl; } } // 重新调度RecordPositions函数以保持每0.005秒记录一次位置 Simulator::Schedule(MilliSeconds(5), &RecordPositions, nodes, std::ref(logFile)); } // Finish std::map<uint32_t, uint64_t> mmWaveBsTraffic; // 基站ID映射到流量(bytes) void InitializeTrafficForBaseStations(const NodeContainer& mmWaveEnbNodes) { Ptr<UniformRandomVariable> randomTraffic = CreateObject<UniformRandomVariable>(); randomTraffic->SetAttribute("Min", DoubleValue(0)); // 最小流量值 randomTraffic->SetAttribute("Max", DoubleValue(100000)); // 最大流量值 for (uint32_t i = 0; i < mmWaveEnbNodes.GetN(); i++) { mmWaveBsTraffic[i] = static_cast<uint64_t>(randomTraffic->GetValue()); if (total_UEs_connected[i] == 0) { mmWaveBsTraffic[i] = 0; } } } #include <unordered_set> // Include this header for unordered_set std::vector<uint32_t> candidateBsList; void PrintSleepTest() { static std::unordered_set<uint32_t> printedBsIds; // This set will keep track of printed IDs for (uint32_t bsId : candidateBsList) { int sleepIndex = bsId + 2; if (sleepIndex < 12 && sleeparray[sleepIndex]) { // Check if the base station should be asleep if (printedBsIds.find(bsId) == printedBsIds.end()) { // Check if the ID has not been printed yet std::cout << "* " << Simulator::Now().GetSeconds() << " CELL " << bsId << " Sleep signal " << sleeparray[sleepIndex] << "\n"; printedBsIds.insert(bsId); // Mark this ID as printed } } } // Optionally clear the set periodically if the context changes or at specific simulation points // printedBsIds.clear(); // ns3::Simulator::Schedule(ns3::Seconds(0.05), &PrintSleepTest); } void PrintBaseStationStatus() { std::cout << "Current Base Station Statuses:\n"; for (size_t i = 0; i < Bs_status.size(); i++) { std::cout << "Base Station " << i << ": " << (Bs_status[i] ? "ON" : "OFF") << "\n"; } } // void CheckAndSwitchBS(){ // InitializeTrafficForBaseStations(mmWaveEnbNodes); // uint32_t numBs = mmWaveBsTraffic.size(); // uint64_t totalTraffic = 0; // for (auto& entry : mmWaveBsTraffic) { // totalTraffic += entry.second; // } // uint64_t trafficThreshold1 = 50000; // for (uint32_t i = 0; i < mmWaveEnbNodes.GetN(); i++) { // uint64_t mmwaveBStraffic = mmWaveBsTraffic[i]; // if (mmwaveBStraffic < trafficThreshold1 || total_UEs_connected[i] == 0) // if (Bs_status[i]) { // std::cout << "Switching off mmWave BS id: " << i << " due to traffic below threshold or no UEs connected and marked for sleep\n"; // candidateBsList.push_back(i); // Ptr<MmWaveEnbPhy> enbPhy = mmWaveEnbNodes.Get(i)->GetDevice(0)->GetObject<MmWaveEnbNetDevice> ()->GetPhy (); // Ptr<MmWaveSpectrumPhy> enbdl= enbPhy->GetDlSpectrumPhy (); // Ptr<MmWaveSpectrumPhy> enbul= enbPhy->GetUlSpectrumPhy (); // Simulator::Schedule(Seconds(0.0001), &MakeBaseStationSleep, enbdl, enbul, true, i);//have to change // // MakeBaseStationSleep(enbdl, enbul, true, i); // Call the function directly // Bs_status[i] = false; // } // } // PrintBaseStationStatus(); // PrintSleepTest(); // Simulator::Schedule(Seconds(0.2), &CheckAndSwitchBS); // 定期更新 // } void CheckAndSwitchBS() { InitializeTrafficForBaseStations(mmWaveEnbNodes); uint32_t numBs = mmWaveBsTraffic.size(); uint64_t totalTraffic = 0; for (auto& entry : mmWaveBsTraffic) { totalTraffic += entry.second; } uint64_t trafficThreshold1 = 40000; uint64_t trafficThreshold2 = (numBs > 0) ? totalTraffic / numBs : 0; candidateBsList.clear(); for (uint32_t i = 0; i < mmWaveEnbNodes.GetN(); i++) { uint64_t mmwaveBStraffic = mmWaveBsTraffic[i]; int sleepIndex = i + 2; if ((mmwaveBStraffic < trafficThreshold1 || total_UEs_connected[i] == 0) && sleepIndex < 12 && sleeparray[sleepIndex]) { if (Bs_status[i]) { std::cout << "Switching off mmWave BS id: " << i << " due to traffic below threshold or no UEs connected and marked for sleep\n"; candidateBsList.push_back(i); Ptr<MmWaveEnbPhy> enbPhy = mmWaveEnbNodes.Get(i)->GetDevice(0)->GetObject<MmWaveEnbNetDevice> ()->GetPhy (); Ptr<MmWaveSpectrumPhy> enbdl= enbPhy->GetDlSpectrumPhy (); Ptr<MmWaveSpectrumPhy> enbul= enbPhy->GetUlSpectrumPhy (); Simulator::Schedule(Seconds(0.0001), &MakeBaseStationSleep, enbdl, enbul, true, i);//have to change // MakeBaseStationSleep(enbdl, enbul, true, i); // Call the function directly Bs_status[i] = false; } // } else if (mmwaveBStraffic > trafficThreshold2 && !sleeparray[sleepIndex]) { } else if (mmwaveBStraffic > trafficThreshold2) { if (!Bs_status[i]) { std::cout << "Switching on mmWave BS id: " << i << " due to traffic above threshold\n"; Ptr<MmWaveEnbPhy> enbPhy = mmWaveEnbNodes.Get(i)->GetDevice(0)->GetObject<MmWaveEnbNetDevice> ()->GetPhy (); Ptr<MmWaveSpectrumPhy> enbdl= enbPhy->GetDlSpectrumPhy (); Ptr<MmWaveSpectrumPhy> enbul= enbPhy->GetUlSpectrumPhy (); Simulator::Schedule(Seconds(0.0001), &MakeBaseStationSleep, enbdl, enbul, false, i);//have to change // MakeBaseStationSleep(enbdl, enbul, false, i);// Call the function directly std::cout << "Wake Up Signal to cell ID: " << i << "\n"; Bs_status[i] = true; } } } // Print the list of BS IDs that have been switched off if (!candidateBsList.empty()) { for (uint32_t bsId : candidateBsList) { std::cout << "Candidate BS ID List: " << bsId << " has connected UEs: " << total_UEs_connected[bsId] << '\n'; } } PrintBaseStationStatus(); PrintSleepTest(); // 打印所有候选基站的睡眠状态 Simulator::Schedule(Seconds(0.2), &CheckAndSwitchBS); // 定期更新 } int main (int argc, char *argv[]) { bool harqEnabled = true; bool fixedTti = false; ns3::RngSeedManager::SetSeed(56); std::list<Box> m_previousBlocks; //ogLevel logLevel = (LogLevel)(LOG_LEVEL_ALL | LOG_PREFIX_TIME | LOG_PREFIX_NODE | LOG_PREFIX_FUNC); //LogComponentEnable("LteEnbRrc", LOG_LEVEL_INFO); //可以確保有從UE-PHY傳上來sleep //LogComponentEnable("MmWaveUePhy", LOG_LEVEL_INFO); //LogComponentEnable("EpcX2", LOG_LEVEL_INFO); // Command line arguments CommandLine cmd; cmd.Parse (argc, argv); UintegerValue uintegerValue; BooleanValue booleanValue; StringValue stringValue; DoubleValue doubleValue; //EnumValue enumValue; GlobalValue::GetValueByName ("numBlocks", uintegerValue); GlobalValue::GetValueByName ("maxXAxis", doubleValue); GlobalValue::GetValueByName ("maxYAxis", doubleValue); //double ueInitialPosition = 90; //double ueFinalPosition = 110; // Variables for the RT int windowForTransient = 150; // number of samples for the vector to use in the filter GlobalValue::GetValueByName ("reportTablePeriodicity", uintegerValue); int ReportTablePeriodicity = (int)uintegerValue.Get (); // in microseconds if (ReportTablePeriodicity == 1600) { windowForTransient = 150; } else if (ReportTablePeriodicity == 25600) { windowForTransient = 50; } else if (ReportTablePeriodicity == 12800) { windowForTransient = 100; } else { NS_ASSERT_MSG (false, "Unrecognized"); } int vectorTransient = windowForTransient * ReportTablePeriodicity; // params for RT, filter, HO mode GlobalValue::GetValueByName ("noiseAndFilter", booleanValue); bool noiseAndFilter = booleanValue.Get (); GlobalValue::GetValueByName ("handoverMode", uintegerValue); uint8_t hoMode = uintegerValue.Get (); GlobalValue::GetValueByName ("outageTh", doubleValue); double outageTh = doubleValue.Get (); GlobalValue::GetValueByName ("rlcAmEnabled", booleanValue); bool rlcAmEnabled = booleanValue.Get (); GlobalValue::GetValueByName ("bufferSize", uintegerValue); uint32_t bufferSize = uintegerValue.Get (); GlobalValue::GetValueByName ("interPckInterval", uintegerValue); uint32_t interPacketInterval = uintegerValue.Get (); GlobalValue::GetValueByName ("x2Latency", doubleValue); double x2Latency = doubleValue.Get (); GlobalValue::GetValueByName ("mmeLatency", doubleValue); double mmeLatency = doubleValue.Get (); GlobalValue::GetValueByName ("mobileSpeed", doubleValue); double ueSpeed = doubleValue.Get (); double transientDuration = double(vectorTransient) / 1000000; //double simTime = transientDuration + ((double)ueFinalPosition - (double)ueInitialPosition) / ueSpeed + 1; double simTime = 5; NS_LOG_UNCOND ("rlcAmEnabled " << rlcAmEnabled << " bufferSize " << bufferSize << " interPacketInterval " << interPacketInterval << " x2Latency " << x2Latency << " mmeLatency " << mmeLatency << " mobileSpeed " << ueSpeed); GlobalValue::GetValueByName ("outPath", stringValue); std::string path = stringValue.Get (); std::string mmWaveOutName = "MmWaveSwitchStats"; std::string lteOutName = "LteSwitchStats"; std::string dlRlcOutName = "DlRlcStats"; std::string dlPdcpOutName = "DlPdcpStats"; std::string ulRlcOutName = "UlRlcStats"; std::string ulPdcpOutName = "UlPdcpStats"; std::string ueHandoverStartOutName = "UeHandoverStartStats"; std::string enbHandoverStartOutName = "EnbHandoverStartStats"; std::string ueHandoverEndOutName = "UeHandoverEndStats"; std::string enbHandoverEndOutName = "EnbHandoverEndStats"; std::string cellIdInTimeOutName = "CellIdStats"; std::string cellIdInTimeHandoverOutName = "CellIdStatsHandover"; std::string mmWaveSinrOutputFilename = "MmWaveSinrTime"; std::string x2statOutputFilename = "X2Stats"; std::string udpSentFilename = "UdpSent"; std::string udpReceivedFilename = "UdpReceived"; std::string extension = ".txt"; std::string version; version = "mc"; Config::SetDefault ("ns3::MmWaveUeMac::UpdateUeSinrEstimatePeriod", DoubleValue (0)); //get current time time_t rawtime; struct tm * timeinfo; char buffer[80]; time (&rawtime); timeinfo = localtime (&rawtime); strftime (buffer,80,"%d_%m_%Y_%I_%M_%S",timeinfo); std::string time_str (buffer); Config::SetDefault ("ns3::MmWaveHelper::RlcAmEnabled", BooleanValue (rlcAmEnabled)); Config::SetDefault ("ns3::MmWaveHelper::HarqEnabled", BooleanValue (harqEnabled)); Config::SetDefault ("ns3::MmWaveFlexTtiMacScheduler::HarqEnabled", BooleanValue (harqEnabled)); Config::SetDefault ("ns3::MmWaveFlexTtiMaxWeightMacScheduler::HarqEnabled", BooleanValue (harqEnabled)); Config::SetDefault ("ns3::MmWaveFlexTtiMaxWeightMacScheduler::FixedTti", BooleanValue (fixedTti)); Config::SetDefault ("ns3::MmWaveFlexTtiMaxWeightMacScheduler::SymPerSlot", UintegerValue (6)); Config::SetDefault ("ns3::MmWavePhyMacCommon::TbDecodeLatency", UintegerValue (200.0)); Config::SetDefault ("ns3::MmWavePhyMacCommon::NumHarqProcess", UintegerValue (100)); Config::SetDefault ("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue (MilliSeconds (100.0))); Config::SetDefault ("ns3::LteEnbRrc::SystemInformationPeriodicity", TimeValue (MilliSeconds (5.0))); Config::SetDefault ("ns3::LteRlcAm::ReportBufferStatusTimer", TimeValue (MicroSeconds (100.0))); Config::SetDefault ("ns3::LteRlcUmLowLat::ReportBufferStatusTimer", TimeValue (MicroSeconds (100.0))); Config::SetDefault ("ns3::LteEnbRrc::SrsPeriodicity", UintegerValue (320)); Config::SetDefault ("ns3::LteEnbRrc::FirstSibTime", UintegerValue (2)); Config::SetDefault ("ns3::MmWavePointToPointEpcHelper::X2LinkDelay", TimeValue (MicroSeconds (x2Latency))); Config::SetDefault ("ns3::MmWavePointToPointEpcHelper::X2LinkDataRate", DataRateValue (DataRate ("1000Gb/s"))); Config::SetDefault ("ns3::MmWavePointToPointEpcHelper::X2LinkMtu", UintegerValue (10000)); Config::SetDefault ("ns3::MmWavePointToPointEpcHelper::S1uLinkDelay", TimeValue (MicroSeconds (1000))); Config::SetDefault ("ns3::MmWavePointToPointEpcHelper::S1apLinkDelay", TimeValue (MicroSeconds (mmeLatency))); Config::SetDefault ("ns3::LteRlcUm::MaxTxBufferSize", UintegerValue (bufferSize * 1024 * 1024)); Config::SetDefault ("ns3::LteRlcUmLowLat::MaxTxBufferSize", UintegerValue (bufferSize * 1024 * 1024)); Config::SetDefault ("ns3::LteRlcAm::StatusProhibitTimer", TimeValue (MilliSeconds (10.0))); Config::SetDefault ("ns3::LteRlcAm::MaxTxBufferSize", UintegerValue (bufferSize * 1024 * 1024)); // handover and RT related params switch (hoMode) { case 1: Config::SetDefault ("ns3::LteEnbRrc::SecondaryCellHandoverMode", EnumValue (LteEnbRrc::THRESHOLD)); break; case 2: Config::SetDefault ("ns3::LteEnbRrc::SecondaryCellHandoverMode", EnumValue (LteEnbRrc::FIXED_TTT)); break; case 3: Config::SetDefault ("ns3::LteEnbRrc::SecondaryCellHandoverMode", EnumValue (LteEnbRrc::DYNAMIC_TTT)); break; } Config::SetDefault ("ns3::LteEnbRrc::FixedTttValue", UintegerValue (150)); Config::SetDefault ("ns3::LteEnbRrc::CrtPeriod", IntegerValue (ReportTablePeriodicity)); Config::SetDefault ("ns3::LteEnbRrc::OutageThreshold", DoubleValue (outageTh)); Config::SetDefault ("ns3::MmWaveEnbPhy::UpdateSinrEstimatePeriod", IntegerValue (ReportTablePeriodicity)); Config::SetDefault ("ns3::MmWaveEnbPhy::Transient", IntegerValue (vectorTransient)); Config::SetDefault ("ns3::MmWaveEnbPhy::NoiseAndFilter", BooleanValue (noiseAndFilter)); // set the type of RRC to use, i.e., ideal or real // by setting the following two attributes to true, the simulation will use // the ideal paradigm, meaning no packets are sent. in fact, only the callbacks are triggered Config::SetDefault ("ns3::MmWaveHelper::UseIdealRrc", BooleanValue(true)); GlobalValue::GetValueByName ("lteUplink", booleanValue); bool lteUplink = booleanValue.Get (); Config::SetDefault ("ns3::McUePdcp::LteUplink", BooleanValue (lteUplink)); std::cout << "Lte uplink " << lteUplink << "\n"; // settings for the 3GPP the channel Config::SetDefault ("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue (MilliSeconds (100))); // interval after which the channel for a moving user is updated, Config::SetDefault ("ns3::ThreeGppChannelModel::Blockage", BooleanValue (true)); // use blockage or not Config::SetDefault ("ns3::ThreeGppChannelModel::PortraitMode", BooleanValue (true)); // use blockage model with UT in portrait mode Config::SetDefault ("ns3::ThreeGppChannelModel::NumNonselfBlocking", IntegerValue (4)); // number of non-self blocking obstacles // by default, isotropic antennas are used. To use the 3GPP radiation pattern instead, use the <ThreeGppAntennaArrayModel> // beware: proper configuration of the bearing and downtilt angles is needed Config::SetDefault ("ns3::PhasedArrayModel::AntennaElement", PointerValue (CreateObject<IsotropicAntennaModel> ())); Ptr<MmWaveHelper> mmwaveHelper = CreateObject<MmWaveHelper> (); mmwaveHelper->SetPathlossModelType ("ns3::ThreeGppUmiStreetCanyonPropagationLossModel"); // mmwaveHelper->SetChannelConditionModelType ("ns3::BuildingsChannelConditionModel"); Ptr<MmWavePointToPointEpcHelper> epcHelper = CreateObject<MmWavePointToPointEpcHelper> (); mmwaveHelper->SetEpcHelper (epcHelper); mmwaveHelper->SetHarqEnabled (harqEnabled); mmwaveHelper->Initialize (); ConfigStore inputConfig; inputConfig.ConfigureDefaults (); // parse again so you can override default values from the command line cmd.Parse (argc, argv); // Get SGW/PGW and create a single RemoteHost Ptr<Node> pgw = epcHelper->GetPgwNode (); NodeContainer remoteHostContainer; remoteHostContainer.Create (1); Ptr<Node> remoteHost = remoteHostContainer.Get (0); InternetStackHelper internet; internet.Install (remoteHostContainer); // Create the Internet by connecting remoteHost to pgw. Setup routing too PointToPointHelper p2ph; p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s"))); p2ph.SetDeviceAttribute ("Mtu", UintegerValue (2500)); p2ph.SetChannelAttribute ("Delay", TimeValue (Seconds (0.010))); NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); Ipv4AddressHelper ipv4h; ipv4h.SetBase ("1.0.0.0", "255.0.0.0"); Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices); // interface 0 is localhost, 1 is the p2p device Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1); Ipv4StaticRoutingHelper ipv4RoutingHelper; Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ()); remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1); // create LTE, mmWave eNB nodes and UE node NodeContainer ueNodes; NodeContainer lteEnbNodes; NodeContainer allEnbNodes; uint16_t num_of_mmWaveEnb = 10; uint32_t num_of_lteEnbNode = 1; uint32_t num_of_UEs = 10; mmWaveEnbNodes.Create (num_of_mmWaveEnb); lteEnbNodes.Create (num_of_lteEnbNode); ueNodes.Create (num_of_UEs); allEnbNodes.Add (lteEnbNodes); allEnbNodes.Add (mmWaveEnbNodes); // Positions // Vector mmw1Position = Vector (50, 70, 3); // Vector mmw2Position = Vector (150, 70, 3); //*********defining position for all 10 ******************|| int p[num_of_mmWaveEnb][2] = {}; deployEnb(p,num_of_mmWaveEnb); std::vector<Ptr<Building> > buildingVector; // Install Mobility Model Ptr<ListPositionAllocator> enbPositionAlloc = CreateObject<ListPositionAllocator>(); // Define grid quarters double centerX = 500; // X coordinate of the grid center double centerY = 500; // Y coordinate of the grid center double quarterWidth = 500 / 2; // Half width of the grid quarter double quarterHeight = 500 / 2; // Half height of the grid quarter // Place base stations in the quarters // Left-Top Quarter: 3 base stations enbPositionAlloc->Add(Vector(centerX - 3.5 * quarterWidth / 4, centerY + 2.5 * quarterHeight / 4, 10)); enbPositionAlloc->Add(Vector(centerX - quarterWidth / 3.5, centerY + quarterHeight / 4, 10)); enbPositionAlloc->Add(Vector(centerX - quarterWidth / 2.5, centerY + 3 * quarterHeight / 4, 10)); // Right-Bottom Quarter: 4 base stations enbPositionAlloc->Add(Vector(centerX + quarterWidth / 4, centerY - quarterHeight / 4, 10)); enbPositionAlloc->Add(Vector(centerX + 3 * quarterWidth / 4, centerY - 3 * quarterHeight / 4, 10)); enbPositionAlloc->Add(Vector(centerX + quarterWidth / 2, centerY - quarterHeight / 2, 10)); enbPositionAlloc->Add(Vector(centerX + 3 * quarterWidth / 4, centerY - quarterHeight / 4, 10)); // Left-Bottom Quarter: 2 base stations enbPositionAlloc->Add(Vector(centerX - 3 * quarterWidth / 4, centerY - quarterHeight / 4, 10)); enbPositionAlloc->Add(Vector(centerX - quarterWidth / 4, centerY - 3 * quarterHeight / 4, 10)); // Right-Top Quarter: 1 base station enbPositionAlloc->Add(Vector(centerX + 3 * quarterWidth / 4, centerY + quarterHeight / 4, 10)); // Set mobility model MobilityHelper enbmobility; enbmobility.SetMobilityModel("ns3::ConstantPositionMobilityModel"); enbmobility.SetPositionAllocator(enbPositionAlloc); enbmobility.Install(allEnbNodes); // RngSeedManager::SetSeed(time(NULL)); // RngSeedManager::SetRun(0); MobilityHelper uemobility; uemobility.SetMobilityModel("ns3::ConstantVelocityMobilityModel"); Ptr<ListPositionAllocator> uePositionAlloc = CreateObject<ListPositionAllocator> (); Ptr<UniformRandomVariable> randomX = CreateObject<UniformRandomVariable>(); Ptr<UniformRandomVariable> randomY = CreateObject<UniformRandomVariable>(); //------------------Fixed UE in specical area-------------- randomX->SetAttribute("Min", DoubleValue(250)); // Min X value randomX->SetAttribute("Max", DoubleValue(500)); // Max X value randomY->SetAttribute("Min", DoubleValue(500)); // Min Y value randomY->SetAttribute("Max", DoubleValue(750)); // Max Y value // 为左下角的4个UE随机分配位置 for (int i = 0; i < 4; ++i) { double x = randomX->GetValue(); double y = randomY->GetValue(); uePositionAlloc->Add(Vector(x, y, 1.5)); } // 为另外两个UE固定分配位置 uePositionAlloc->Add(Vector(500.5, 400.5, 1.5)); // 固定位置1 uePositionAlloc->Add(Vector(270.5, 450.5, 1.5)); // 固定位置2 // for (int i = 0; i < 6; ++i) { // uePositionAlloc->Add(Vector(300 + i * 10, 700 + i * 5, 1.5)); // } uePositionAlloc->Add(Vector(600.5, 350.5, 1.5)); uePositionAlloc->Add(Vector(660.5, 340.5, 1.5)); uePositionAlloc->Add(Vector(450.5, 350.5, 1.5)); uePositionAlloc->Add(Vector(600.5, 600.5, 1.5)); std::vector<ns3::Vector> initialPositions; uemobility.SetPositionAllocator(uePositionAlloc); uemobility.Install(ueNodes); PrintUEPositions(ueNodes); Vector velocity(30.0, -50.0, 0.0); // // Vector velocity(150.0, -250.0, 0.0); // // Vector velocity(75.0, -125.0, 0.0); // // Vector velocity(300.0, -500.0, 0.0); // // Vector velocity(90.0, -150.0, 0.0); // Time downtown_stopTime = Seconds(0.35); // Time downtown_stopTime = Seconds(0.75); // // Time startTime = Seconds(0.4); // Time startTime = Seconds(1.5); // // Time reverseStartTime = Seconds(0.25); Time reverseStartTime; for (uint32_t i = 0; i < ueNodes.GetN(); ++i) { if (i < 4) { // 只有左下角的前4個UE會移動 Simulator::Schedule(Seconds(0.25), &UpdatePosition, ueNodes.Get(i), velocity, downtown_stopTime, startTime, false, reverseStartTime); // Simulator::Schedule(Seconds (simTime - 3), &ChangeSpeed, ueNodes.Get (i), Vector (0, 0, 0)); } } Simulator::Schedule(Seconds(0.25), &RecordPositions, ueNodes, std::ref(positionLogFile)); // Install mmWave, lte, mc Devices to the nodes NetDeviceContainer lteEnbDevs = mmwaveHelper->InstallLteEnbDevice (lteEnbNodes); NetDeviceContainer mmWaveEnbDevs = mmwaveHelper->InstallEnbDevice (mmWaveEnbNodes); NetDeviceContainer mcUeDevs; mcUeDevs = mmwaveHelper->InstallMcUeDevice (ueNodes); // Install the IP stack on the UEs internet.Install (ueNodes); Ipv4InterfaceContainer ueIpIface; ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (mcUeDevs)); // Assign IP address to UEs, and install applications for (uint32_t u = 0; u < ueNodes.GetN (); ++u) { Ptr<Node> ueNode = ueNodes.Get (u); // Set the default gateway for the UE Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ()); ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1); } // Add X2 interfaces mmwaveHelper->AddX2Interface (lteEnbNodes, mmWaveEnbNodes); // Manual attachment mmwaveHelper->AttachToClosestEnb (mcUeDevs, mmWaveEnbDevs, lteEnbDevs); //Populating mmWave Base Station Id with position in map BS_position. for(uint32_t i = 0; i < mmWaveEnbNodes.GetN(); i++) { Ptr<Node> node = mmWaveEnbNodes.Get(i); // 獲取節點指針 Ptr<MobilityModel> mobility = node->GetObject<MobilityModel>(); // 獲取移動模型 Vector pos = mobility->GetPosition(); // 獲取位置 Bs_positions[i] = pos; total_UEs_connected[i] = 0; Bs_status[i] = true; Ptr<MmWaveEnbNetDevice> netDevice = node->GetDevice(0)->GetObject<MmWaveEnbNetDevice>(); // 假設每個節點有一個裝置且這個裝置是毫米波網路裝置 uint16_t cellId = netDevice->GetCellId(); // 獲取Cell ID std::cout << "mmWave Base Station node ID = " << i << ", cell ID = " << cellId << std::endl; } //populating Number of UEs connected to a particular mmWave Base Station. for(uint32_t i = 0 ; i < ueNodes.GetN() ; i++) { Vector UEpos = ueNodes.Get(i)->GetObject<MobilityModel> ()->GetPosition (); uint32_t nearest_bs_id = 0; Vector naerest_bs_pos = mmWaveEnbNodes.Get(0)->GetObject<MobilityModel>()->GetPosition(); for(auto j : Bs_positions) { if(j.first == 0) continue; Vector bs_pos = j.second; if(pow(UEpos.x-bs_pos.x,2)+pow(UEpos.y-bs_pos.y,2) < pow(UEpos.x - naerest_bs_pos.x,2)+pow(UEpos.y-naerest_bs_pos.y,2)) { naerest_bs_pos = bs_pos; nearest_bs_id = j.first; } } current_Bs[i] = nearest_bs_id; total_UEs_connected[nearest_bs_id]++; std::cout<< "Nearest BS of UE ," << i <<" is "<<nearest_bs_id <<std::endl; } // std::cout<<"Out_of_loop"; for(auto i : total_UEs_connected) { std::cout<<"No of UEs connected to this BS" <<i.first<<" are : "<< i.second<<std::endl; } // for(uint32_t uid = 0 ; uid < ueNodes.GetN(); uid++) // { // Ptr<MobilityModel> mModel = ueNodes.Get(uid)->GetObject<MobilityModel>(); // Vector UE_pos = mModel->GetPosition(); // mModel->TraceConnectWithoutContext("CourseChange",MakeBoundCallback(&SwitchOffIdleBaseStation, UE_pos, uid)); // } Simulator::Schedule(Seconds(0.25), &CheckAndSwitchBS); //*******************Trace_Source_of_UE_position_and_Call_SwitchOffIdleBaseStation***********************************|| //*******************************************************************************************************************|| //********************************************************************************************************************************** // Installing Energy Source BasicEnergySourceHelper basicSourceHelper; basicSourceHelper.Set("BasicEnergySourceInitialEnergyJ", DoubleValue(100000000000000.0)); basicSourceHelper.Set("BasicEnergySupplyVoltageV", DoubleValue(5.0)); // basicSourceHelper.Set ("BasicEnergySourceInitialEnergyJ", DoubleValue (1000000)); // basicSourceHelper.Set ("BasicEnergySupplyVoltageV", DoubleValue (5.0)); // Install Energy Source EnergySourceContainer sources = basicSourceHelper.Install (ueNodes); EnergySourceContainer Enb_sources = basicSourceHelper.Install (mmWaveEnbNodes); // mmwave_phy = mmWaveEnbNodes.Get(0)->GetDevice(0)->GetObject<MmWaveEnbNetDevice>()->GetPhy(); MmWaveRadioEnergyModelHelper nrEnergyHelper; MmWaveRadioEnergyModelEnbHelper enbEnergyHelper; DeviceEnergyModelContainer deviceEnergyModel = nrEnergyHelper.Install (mcUeDevs, sources); DeviceEnergyModelContainer bsEnergyModel = enbEnergyHelper.Install (mmWaveEnbDevs, Enb_sources); for (uint32_t u = 0; u < mmWaveEnbNodes.GetN (); ++u) { // Install Energy Source Ptr<MmWaveEnbNetDevice> mmdev = DynamicCast<MmWaveEnbNetDevice> (mmWaveEnbNodes.Get(u)->GetDevice(0)); //check here deviceEnergyModel.Get(u)->TraceConnectWithoutContext ("TotalEnergyConsumption", MakeBoundCallback (&EnergyConsumptionUpdate, u)); bsEnergyModel.Get(u)->TraceConnectWithoutContext ("TotalEnergyConsumption", MakeBoundCallback (&EnergyConsumptionUpdateBS, u)); } // deviceEnergyModel.Get(0)->TraceConnectWithoutContext ("TotalEnergyConsumption", MakeCallback (&EnergyConsumptionUpdate)); // bsEnergyModel.Get(0)->TraceConnectWithoutContext ("TotalEnergyConsumption", MakeCallback (&EnergyConsumptionUpdateBS)); // Install and start applications on UEs and remote host uint16_t dlPort = 1234; uint16_t ulPort = 2000; ApplicationContainer clientApps; ApplicationContainer serverApps; bool dl = 1; bool ul = 0; for (uint32_t u = 0; u < ueNodes.GetN (); ++u) { if (dl) { UdpServerHelper dlPacketSinkHelper (dlPort); dlPacketSinkHelper.SetAttribute ("PacketWindowSize", UintegerValue (256)); serverApps.Add (dlPacketSinkHelper.Install (ueNodes.Get (u))); // Simulator::Schedule(MilliSeconds(20), &PrintLostUdpPackets, DynamicCast<UdpServer>(serverApps.Get(serverApps.GetN()-1)), lostFilename); UdpClientHelper dlClient (ueIpIface.GetAddress (u), dlPort); dlClient.SetAttribute ("Interval", TimeValue (MicroSeconds (interPacketInterval))); dlClient.SetAttribute ("MaxPackets", UintegerValue (0xFFFFFFFF)); clientApps.Add (dlClient.Install (remoteHost)); } if (ul) { ++ulPort; PacketSinkHelper ulPacketSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), ulPort)); ulPacketSinkHelper.SetAttribute ("PacketWindowSize", UintegerValue (256)); serverApps.Add (ulPacketSinkHelper.Install (remoteHost)); UdpClientHelper ulClient (remoteHostAddr, ulPort); ulClient.SetAttribute ("Interval", TimeValue (MicroSeconds (interPacketInterval))); ulClient.SetAttribute ("MaxPackets", UintegerValue (0xFFFFFFFF)); clientApps.Add (ulClient.Install (ueNodes.Get (u))); } } // Start applications NS_LOG_UNCOND ("transientDuration " << transientDuration << " simTime " << simTime); serverApps.Start (Seconds (transientDuration)); clientApps.Start (Seconds (transientDuration)); clientApps.Stop (Seconds (simTime - 1)); //Simulator::Schedule (Seconds (transientDuration), &ChangeSpeed, ueNodes.Get (0), Vector (ueSpeed, 0, 0)); // start UE movement after Seconds(0.5) // Simulator::Schedule (Seconds (simTime - 1), &ChangeSpeed, ueNodes.Get (0), Vector (0, 0, 0)); // start UE movement after Seconds(0.5) // MWNL // Config::ConnectFailSafe ("/NodeList/*/DeviceList/*/LteEnbRrc/NotifyMmWaveTarget", // MakeBoundCallback (&NotifyMmWaveTarget)); // Config::ConnectFailSafe ("/NodeList/*/DeviceList/*/LteEnbRrc/NotifyMmWaveSinr", // MakeBoundCallback (&NotifyMmWaveSinr)); // Config::ConnectFailSafe ("/NodeList/*/DeviceList/*/LteEnbRrc/NotifyMmWaveServing", // MakeBoundCallback (&NotifyMmWaveServing)); Config::ConnectFailSafe ("/NodeList/*/DeviceList/*/LteEnbRrc/NotifyMmWaveSleep", MakeBoundCallback (&NotifyMmWaveSleep)); double numPrints = 0; for (int i = 0; i < numPrints; i++) { Simulator::Schedule (Seconds (i * simTime / numPrints), &PrintPosition, ueNodes.Get (0)); } mmwaveHelper->EnableTraces (); // ns3::Simulator::Schedule(ns3::Seconds(0.20), &PrintSleepTest); // set to true if you want to print the map of buildings, ues and enbs bool print = false; if (print) { PrintGnuplottableBuildingListToFile ("buildings.txt"); PrintGnuplottableUeListToFile ("ues.txt"); PrintGnuplottableEnbListToFile ("enbs.txt"); } else { positionLogFile.open("positionLog.txt"); Simulator::Stop (Seconds (simTime)); AnimationInterface anim ("ue_pos.xml"); Simulator::Run (); positionLogFile.close(); logFile.close(); } Simulator::Destroy (); return 0; } ```