From b81a765c5f7839efe1de1e5b971adaf94d4620f8 Mon Sep 17 00:00:00 2001 From: Matteo Drago Date: Mon, 26 Sep 2022 14:00:10 +0200 Subject: [PATCH] Update MilliCar to ns-3.36.1 and ns3-mmwave latest updates (#174) * Delete classes that have been integrated in ns-3 main repo * Update method name and delete comments * Make beamforming model configurable by the user * Init new channel model config * Add method to create spectrum channel * Add CMakeLists.txt * Add CMakeLists for examples * Fix file for CI configuration * Fix examples * Fix warnings on pointers * Change code to support changes of spectrum channel model * Delete wscript * Remove mmwave-vehicular-link-adaptation-example Co-authored-by: tommasozugno --- .github/workflows/main.yml | 5 +- CMakeLists.txt | 42 + examples/CMakeLists.txt | 23 + ...mwave-vehicular-link-adaptation-example.cc | 105 - examples/vehicular-simple-four.cc | 21 +- examples/vehicular-simple-one.cc | 76 +- examples/vehicular-simple-three.cc | 27 +- examples/vehicular-simple-two.cc | 37 +- examples/wscript | 18 - helper/mmwave-vehicular-helper.cc | 165 +- helper/mmwave-vehicular-helper.h | 41 +- model/mmwave-sidelink-spectrum-phy.cc | 35 +- model/mmwave-sidelink-spectrum-phy.h | 19 +- ...ave-sidelink-spectrum-signal-parameters.cc | 12 +- ...wave-sidelink-spectrum-signal-parameters.h | 2 +- model/mmwave-vehicular-antenna-array-model.cc | 4 +- model/mmwave-vehicular-net-device.cc | 14 + model/mmwave-vehicular-net-device.h | 15 + ...mmwave-vehicular-propagation-loss-model.cc | 564 ---- .../mmwave-vehicular-propagation-loss-model.h | 131 - ...hicular-spectrum-propagation-loss-model.cc | 2499 ----------------- ...ehicular-spectrum-propagation-loss-model.h | 365 --- test/mmwave-vehicular-interference-test.cc | 11 +- test/mmwave-vehicular-rate-test.cc | 10 +- test/mmwave-vehicular-spectrum-phy-test.cc | 10 +- wscript | 52 - 26 files changed, 383 insertions(+), 3920 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 examples/CMakeLists.txt delete mode 100644 examples/mmwave-vehicular-link-adaptation-example.cc delete mode 100644 examples/wscript delete mode 100644 model/mmwave-vehicular-propagation-loss-model.cc delete mode 100644 model/mmwave-vehicular-propagation-loss-model.h delete mode 100644 model/mmwave-vehicular-spectrum-propagation-loss-model.cc delete mode 100644 model/mmwave-vehicular-spectrum-propagation-loss-model.h delete mode 100644 wscript diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 20d8a90..23f23e6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,9 +31,6 @@ jobs: - name: check that millicar is correctly installed run: ls src/ | grep millicar - - - name: enable only millicar - run: printf "#! /usr/bin/env python \n modules_enabled = ['millicar']" > .ns3rc - name: build and run the tests - run: ./waf configure --enable-examples --enable-tests && ./waf build && ./test.py + run: ./ns3 configure --enable-examples --enable-tests --enable-modules=millicar && ./ns3 build && ./test.py diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8f6c2b1 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,42 @@ +set(source_files + model/mmwave-vehicular.cc + model/mmwave-sidelink-spectrum-phy.cc + model/mmwave-sidelink-spectrum-signal-parameters.cc + model/mmwave-sidelink-phy.cc + model/mmwave-sidelink-mac.cc + model/mmwave-vehicular-net-device.cc + model/mmwave-vehicular-antenna-array-model.cc + helper/mmwave-vehicular-helper.cc + helper/mmwave-vehicular-traces-helper.cc +) + +set(test_sources + test/mmwave-vehicular-spectrum-phy-test.cc + test/mmwave-vehicular-rate-test.cc + test/mmwave-vehicular-interference-test.cc +) + +set(header_files + model/mmwave-vehicular.h + model/mmwave-sidelink-spectrum-phy.h + model/mmwave-sidelink-spectrum-signal-parameters.h + model/mmwave-sidelink-phy.h + model/mmwave-sidelink-mac.h + model/mmwave-sidelink-sap.h + model/mmwave-vehicular-net-device.h + model/mmwave-vehicular-antenna-array-model.h + helper/mmwave-vehicular-helper.h + helper/mmwave-vehicular-traces-helper.h +) + +build_lib( + LIBNAME millicar + SOURCE_FILES ${source_files} + HEADER_FILES ${header_files} + LIBRARIES_TO_LINK + ${libcore} + ${libpropagation} + ${libspectrum} + ${libmmwave} + TEST_SOURCES ${test_sources} +) \ No newline at end of file diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..c0772c6 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,23 @@ +set(base_examples + vehicular-simple-one + vehicular-simple-two + vehicular-simple-three + vehicular-simple-four + mmwave-vehicular-link-adaptation-example +) + +foreach( + example + ${base_examples} +) + build_lib_example( + NAME ${example} + SOURCE_FILES ${example}.cc + LIBRARIES_TO_LINK + ${libmillicar} + ${libcore} + ${libpropagation} + ${libspectrum} + ${libmmwave} + ) +endforeach() \ No newline at end of file diff --git a/examples/mmwave-vehicular-link-adaptation-example.cc b/examples/mmwave-vehicular-link-adaptation-example.cc deleted file mode 100644 index ba1ccb7..0000000 --- a/examples/mmwave-vehicular-link-adaptation-example.cc +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* -* Copyright (c) 2020 University of Padova, Dep. of Information Engineering, -* SIGNET lab. -* -* 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 -*/ - -#include "ns3/mmwave-vehicular-net-device.h" -#include "ns3/mmwave-vehicular-helper.h" -#include "ns3/mobility-module.h" -#include "ns3/internet-module.h" -#include "ns3/core-module.h" -#include -#include "ns3/applications-module.h" - -using namespace ns3; -using namespace millicar; - -NS_LOG_COMPONENT_DEFINE ("MmWaveVehicularLinkAdaptationExample"); - -/** - * In this example there are two nodes, one is stationary while the other is - * moving at a constant speed, and they exchange messages at a constant rate. - * The simulation produces the file sinr-mcs.txt containg the - * MCS selected for each transmission. - */ -int -main (int argc, char *argv[]) -{ - double initialDistance = 10.0; // the initial distance between the two nodes in m - double finalDistance = 10000.0; // the final distance between the two nodes in m - double speed = 100.0; // the speed of the moving node in m/s - double frequency = 60e9; // the carrier frequency - - double endTime = (finalDistance - initialDistance) / speed; // time required for the simulation - - Config::SetDefault ("ns3::MmWaveSidelinkMac::UseAmc", BooleanValue (true)); - Config::SetDefault ("ns3::MmWavePhyMacCommon::CenterFreq", DoubleValue (frequency)); - Config::SetDefault ("ns3::MmWaveVehicularPropagationLossModel::ChannelCondition", StringValue ("l")); - Config::SetDefault ("ns3::MmWaveVehicularHelper::SchedulingPatternOption", EnumValue(2)); // use 2 for SchedulingPatternOption=OPTIMIZED, 1 or SchedulingPatternOption=DEFAULT - Config::SetDefault ("ns3::MmWaveVehicularNetDevice::RlcType", StringValue("LteRlcUm")); - Config::SetDefault ("ns3::LteRlcUm::MaxTxBufferSize", UintegerValue (50*1024)); - - // create the nodes - NodeContainer n; - n.Create (2); - - // create the mobility models - MobilityHelper mobility; - mobility.SetMobilityModel ("ns3::ConstantVelocityMobilityModel"); - mobility.Install (n); - - n.Get (0)->GetObject ()->SetPosition (Vector (0, 0, 0)); - n.Get (0)->GetObject ()->SetVelocity (Vector (0, 0, 0)); - - n.Get (1)->GetObject ()->SetPosition (Vector (initialDistance, 0, 0)); - n.Get (1)->GetObject ()->SetVelocity (Vector (speed, 0, 0)); - - // create and configure the helper - Ptr helper = CreateObject (); - helper->SetNumerology (3); - helper->SetPropagationLossModelType ("ns3::MmWaveVehicularPropagationLossModel"); - helper->SetSpectrumPropagationLossModelType ("ns3::MmWaveVehicularSpectrumPropagationLossModel"); - NetDeviceContainer devs = helper->InstallMmWaveVehicularNetDevices (n); - - // Install the TCP/IP stack in the two nodes - InternetStackHelper internet; - internet.Install (n); - - Ipv4AddressHelper ipv4; - NS_LOG_INFO ("Assign IP Addresses."); - ipv4.SetBase ("10.1.1.0", "255.255.255.0"); - Ipv4InterfaceContainer i = ipv4.Assign (devs); - - // Need to pair the devices in order to create a correspondence between transmitter and receiver - // and to populate the < IP addr, RNTI > map. - helper->PairDevices(devs); - - UdpClientHelper client (n.Get (1)->GetObject ()->GetAddress (1, 0).GetLocal (), 4000); - client.SetAttribute ("MaxPackets", UintegerValue (0xFFFFF)); - client.SetAttribute ("Interval", TimeValue (MilliSeconds (1))); - client.SetAttribute ("PacketSize", UintegerValue (512)); - ApplicationContainer clientApps = client.Install (n.Get (0)); - clientApps.Start (Seconds(1.0)); - - UdpEchoServerHelper server (4000); - ApplicationContainer serverApps = server.Install (n.Get (1)); - serverApps.Start (Seconds (0.0)); - - Simulator::Stop (Seconds (endTime)); - Simulator::Run (); - Simulator::Destroy (); -} diff --git a/examples/vehicular-simple-four.cc b/examples/vehicular-simple-four.cc index 10085c8..e5b8804 100644 --- a/examples/vehicular-simple-four.cc +++ b/examples/vehicular-simple-four.cc @@ -26,8 +26,10 @@ #include "ns3/spectrum-helper.h" #include "ns3/mmwave-spectrum-value-helper.h" #include "ns3/applications-module.h" +#include "ns3/buildings-module.h" #include "ns3/internet-module.h" -#include "ns3/core-module.h" +#include "ns3/config.h" +#include "ns3/command-line.h" NS_LOG_COMPONENT_DEFINE ("VehicularSimpleFour"); @@ -56,21 +58,25 @@ int main (int argc, char *argv[]) Time endTime = Seconds (10.0); double bandwidth = 1e8; + std::string scenario = "V2V-Urban"; double speed = 20; // m/s CommandLine cmd; cmd.AddValue ("vehicleSpeed", "The speed of the vehicle", speed); + cmd.AddValue ("scenario", "set the vehicular scenario", scenario); cmd.Parse (argc, argv); Config::SetDefault ("ns3::MmWaveSidelinkMac::UseAmc", BooleanValue (true)); - //Config::SetDefault ("ns3::MmWaveSidelinkMac::Mcs", UintegerValue (28)); + Config::SetDefault ("ns3::MmWaveSidelinkMac::Mcs", UintegerValue (28)); Config::SetDefault ("ns3::MmWavePhyMacCommon::CenterFreq", DoubleValue (60.0e9)); Config::SetDefault ("ns3::MmWaveVehicularNetDevice::RlcType", StringValue("LteRlcUm")); Config::SetDefault ("ns3::LteRlcUm::MaxTxBufferSize", UintegerValue (50*1024)); - Config::SetDefault ("ns3::MmWaveVehicularPropagationLossModel::ChannelCondition", StringValue ("l")); - Config::SetDefault ("ns3::MmWaveVehicularHelper::Bandwidth", DoubleValue (bandwidth)); + Config::SetDefault ("ns3::MmWaveVehicularHelper::SchedulingPatternOption", EnumValue(2)); // use 2 for SchedulingPatternOption=OPTIMIZED, 1 or SchedulingPatternOption=DEFAULT + Config::SetDefault ("ns3::MmWaveVehicularHelper::Bandwidth", DoubleValue (bandwidth)); + Config::SetDefault ("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue (MilliSeconds (10))); + // create the nodes NodeContainer group; group.Create (3); @@ -91,10 +97,13 @@ int main (int argc, char *argv[]) // create and configure the helper Ptr helper = CreateObject (); - helper->SetPropagationLossModelType ("ns3::MmWaveVehicularPropagationLossModel"); - helper->SetSpectrumPropagationLossModelType ("ns3::MmWaveVehicularSpectrumPropagationLossModel"); helper->SetNumerology (3); + helper->SetChannelModelType (scenario); NetDeviceContainer devs = helper->InstallMmWaveVehicularNetDevices (group); + + // Mandatory to install buildings helper even if there are no buildings, + // otherwise V2V-Urban scenario does not work + BuildingsHelper::Install (group); InternetStackHelper internet; internet.Install (group); diff --git a/examples/vehicular-simple-one.cc b/examples/vehicular-simple-one.cc index c77501b..6c568e6 100644 --- a/examples/vehicular-simple-one.cc +++ b/examples/vehicular-simple-one.cc @@ -28,13 +28,17 @@ #include "ns3/mmwave-spectrum-value-helper.h" #include "ns3/applications-module.h" #include "ns3/internet-module.h" -#include "ns3/core-module.h" +#include "ns3/buildings-module.h" +#include "ns3/command-line.h" +#include "ns3/node-list.h" NS_LOG_COMPONENT_DEFINE ("VehicularSimpleOne"); using namespace ns3; using namespace millicar; +void PrintGnuplottableNodeListToFile (std::string filename); + uint32_t g_rxPackets; // total number of received packets uint32_t g_txPackets; // total number of transmitted packets @@ -81,27 +85,28 @@ int main (int argc, char *argv[]) // mobility double speed = 20; // speed of the vehicles m/s double intraGroupDistance = 10; // distance between two vehicles belonging to the same group + + std::string scenario = "V2V-Urban"; CommandLine cmd; - // cmd.AddValue ("bandwidth", "used bandwidth", bandwidth); cmd.AddValue ("iip", "inter packet interval, in microseconds", interPacketInterval); cmd.AddValue ("intraGroupDistance", "distance between two vehicles belonging to the same group, y-coord", intraGroupDistance); cmd.AddValue ("numerology", "set the numerology to use at the physical layer", numerology); cmd.AddValue ("frequency", "set the carrier frequency", frequency); + cmd.AddValue ("scenario", "set the vehicular scenario", scenario); cmd.Parse (argc, argv); Config::SetDefault ("ns3::MmWaveSidelinkMac::UseAmc", BooleanValue (true)); + Config::SetDefault ("ns3::MmWaveSidelinkMac::Mcs", UintegerValue (28)); Config::SetDefault ("ns3::MmWavePhyMacCommon::CenterFreq", DoubleValue (frequency)); + Config::SetDefault ("ns3::MmWaveVehicularHelper::Bandwidth", DoubleValue (bandwidth)); Config::SetDefault ("ns3::MmWaveVehicularHelper::Numerology", UintegerValue (numerology)); - Config::SetDefault ("ns3::MmWaveVehicularPropagationLossModel::ChannelCondition", StringValue ("a")); - Config::SetDefault ("ns3::MmWaveVehicularPropagationLossModel::Shadowing", BooleanValue (true)); - Config::SetDefault ("ns3::MmWaveVehicularSpectrumPropagationLossModel::UpdatePeriod", TimeValue (MilliSeconds (1))); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::AntennaElements", UintegerValue (16)); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::AntennaElementPattern", StringValue ("3GPP-V2V")); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::IsotropicAntennaElements", BooleanValue (true)); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::NumSectors", UintegerValue (2)); + Config::SetDefault ("ns3::MmWaveVehicularHelper::ChannelModelType", StringValue (scenario)); + + Config::SetDefault ("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue (MilliSeconds (10))); + Config::SetDefault ("ns3::ThreeGppChannelConditionModel::UpdatePeriod", TimeValue (MilliSeconds (10))); Config::SetDefault ("ns3::MmWaveVehicularNetDevice::RlcType", StringValue("LteRlcUm")); Config::SetDefault ("ns3::MmWaveVehicularHelper::SchedulingPatternOption", EnumValue(2)); // use 2 for SchedulingPatternOption=OPTIMIZED, 1 or SchedulingPatternOption=DEFAULT @@ -124,12 +129,9 @@ int main (int argc, char *argv[]) // create and configure the helper Ptr helper = CreateObject (); helper->SetNumerology (3); - helper->SetPropagationLossModelType ("ns3::MmWaveVehicularPropagationLossModel"); - helper->SetSpectrumPropagationLossModelType ("ns3::MmWaveVehicularSpectrumPropagationLossModel"); NetDeviceContainer devs = helper->InstallMmWaveVehicularNetDevices (n); // Install the TCP/IP stack in the two nodes - InternetStackHelper internet; internet.Install (n); @@ -137,6 +139,10 @@ int main (int argc, char *argv[]) NS_LOG_INFO ("Assign IP Addresses."); ipv4.SetBase ("10.1.1.0", "255.255.255.0"); Ipv4InterfaceContainer i = ipv4.Assign (devs); + + // Mandatory to install buildings helper even if there are no buildings, + // otherwise V2V-Urban scenario does not work + BuildingsHelper::Install (n); // Need to pair the devices in order to create a correspondence between transmitter and receiver // and to populate the < IP addr, RNTI > map. @@ -174,7 +180,9 @@ int main (int argc, char *argv[]) // set the application start/end time apps.Start (MilliSeconds (startTime)); apps.Stop (MilliSeconds (endTime)); - + + PrintGnuplottableNodeListToFile ("scenario.txt"); + Simulator::Stop (MilliSeconds (endTime + 1000)); Simulator::Run (); Simulator::Destroy (); @@ -186,3 +194,45 @@ int main (int argc, char *argv[]) return 0; } + +void +PrintGnuplottableNodeListToFile (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; + } + outFile << "set xrange [-200:200]; set yrange [-200:200]" << std::endl; + for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it) + { + Ptr node = *it; + int nDevs = node->GetNDevices (); + for (int j = 0; j < nDevs; j++) + { + Ptr vdev = node->GetDevice (j)->GetObject (); + if (vdev) + { + Vector pos = node->GetObject ()->GetPosition (); + outFile << "set label \"" << vdev->GetMac ()->GetRnti () + << "\" at "<< pos.x << "," << pos.y << " left font \"Helvetica,8\" textcolor rgb \"black\" front point pt 7 ps 0.3 lc rgb \"black\" offset 0,0" + << std::endl; + + // Simulator::Schedule (Seconds (1), &PrintHelper::UpdateGnuplottableNodeListToFile, filename, node); + } + } + } + + 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 + << std::endl; + } +} diff --git a/examples/vehicular-simple-three.cc b/examples/vehicular-simple-three.cc index c51afce..36b5e23 100644 --- a/examples/vehicular-simple-three.cc +++ b/examples/vehicular-simple-three.cc @@ -23,8 +23,10 @@ #include "ns3/mobility-module.h" #include "ns3/mmwave-spectrum-value-helper.h" #include "ns3/applications-module.h" +#include "ns3/buildings-module.h" #include "ns3/internet-module.h" -#include "ns3/core-module.h" +#include "ns3/config.h" +#include "ns3/command-line.h" NS_LOG_COMPONENT_DEFINE ("VehicularSimpleThree"); @@ -109,6 +111,7 @@ int main (int argc, char *argv[]) uint32_t numAntennaElements = 4; // number of antenna elements bool orthogonalResources = true; // if true, resouces are orthogonal among the two groups, if false resources are shared + std::string scenario = "V2V-Highway"; CommandLine cmd; cmd.AddValue ("startTime", "application stop time in milliseconds", startTime); @@ -122,20 +125,22 @@ int main (int argc, char *argv[]) cmd.AddValue ("numAntennaElements", "number of antenna elements", numAntennaElements); cmd.AddValue ("orthogonalResources", "if true, resouces are orthogonal among the two groups, if false resources are shared", orthogonalResources); cmd.AddValue ("sameLane", "if true the two groups lie on the same lane, if false they lie on adjacent lanes", sameLane); + cmd.AddValue ("scenario", "set the vehicular scenario", scenario); cmd.Parse (argc, argv); Config::SetDefault ("ns3::MmWaveSidelinkMac::UseAmc", BooleanValue (false)); Config::SetDefault ("ns3::MmWaveSidelinkMac::Mcs", UintegerValue (mcs)); Config::SetDefault ("ns3::MmWavePhyMacCommon::CenterFreq", DoubleValue (28.0e9)); - Config::SetDefault ("ns3::MmWaveVehicularPropagationLossModel::ChannelCondition", StringValue ("l")); Config::SetDefault ("ns3::MmWaveVehicularNetDevice::RlcType", StringValue("LteRlcUm")); + Config::SetDefault ("ns3::MmWaveVehicularHelper::SchedulingPatternOption", EnumValue(2)); // use 2 for SchedulingPatternOption=OPTIMIZED, 1 or SchedulingPatternOption=DEFAULT + + Config::SetDefault ("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue (MilliSeconds (10))); + Config::SetDefault ("ns3::LteRlcUm::MaxTxBufferSize", UintegerValue (500*1024)); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::AntennaElements", UintegerValue (numAntennaElements)); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::AntennaElementPattern", StringValue ("3GPP-V2V")); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::IsotropicAntennaElements", BooleanValue (true)); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::NumSectors", UintegerValue (2)); + Config::SetDefault ("ns3::UniformPlanarArray::NumColumns", UintegerValue (std::sqrt (numAntennaElements))); + Config::SetDefault ("ns3::UniformPlanarArray::NumRows", UintegerValue (std::sqrt (numAntennaElements))); // create the nodes NodeContainer group1, group2; @@ -172,8 +177,7 @@ int main (int argc, char *argv[]) // create and configure the helper Ptr helper = CreateObject (); helper->SetNumerology (3); - helper->SetPropagationLossModelType ("ns3::MmWaveVehicularPropagationLossModel"); - helper->SetSpectrumPropagationLossModelType ("ns3::MmWaveVehicularSpectrumPropagationLossModel"); + helper->SetChannelModelType (scenario); NetDeviceContainer devs1 = helper->InstallMmWaveVehicularNetDevices (group1); NetDeviceContainer devs2 = helper->InstallMmWaveVehicularNetDevices (group2); @@ -214,6 +218,11 @@ int main (int argc, char *argv[]) staticRouting = ipv4RoutingHelper.GetStaticRouting (group2.Get (0)->GetObject ()); staticRouting->SetDefaultRoute (group2.Get (1)->GetObject ()->GetAddress (1, 0).GetLocal () , 2 ); + // Mandatory to install buildings helper even if there are no buildings, + // otherwise V2V-Urban scenario does not work + BuildingsHelper::Install (group1); + BuildingsHelper::Install (group2); + // create the random variables used to setup the applications Ptr onPeriodRv = CreateObjectWithAttributes ("Constant", DoubleValue (onPeriod / 1000.0)); Ptr offPeriodRv = CreateObjectWithAttributes ("Mean", DoubleValue (offPeriod / 1000.0)); @@ -225,7 +234,7 @@ int main (int argc, char *argv[]) onoff.SetAttribute ("OnTime", PointerValue (onPeriodRv)); onoff.SetAttribute ("OffTime", PointerValue (offPeriodRv)); ApplicationContainer onOffApps = onoff.Install (group1.Get (0)); - + PacketSinkHelper sink ("ns3::UdpSocketFactory", Address (InetSocketAddress (Ipv4Address::GetAny (), port))); ApplicationContainer packetSinkApps = sink.Install (group1.Get (1)); diff --git a/examples/vehicular-simple-two.cc b/examples/vehicular-simple-two.cc index ac0fc2e..67abc57 100644 --- a/examples/vehicular-simple-two.cc +++ b/examples/vehicular-simple-two.cc @@ -27,7 +27,9 @@ #include "ns3/mmwave-spectrum-value-helper.h" #include "ns3/applications-module.h" #include "ns3/internet-module.h" -#include "ns3/core-module.h" +#include "ns3/buildings-module.h" +#include "ns3/config.h" +#include "ns3/command-line.h" #include "ns3/node-list.h" NS_LOG_COMPONENT_DEFINE ("VehicularSimpleTwo"); @@ -62,24 +64,21 @@ int main (int argc, char *argv[]) double interGroupInitialDistance = 40; // initial distance between the two groups double laneDistance = 5.0; // distance between the two lanes double antennaHeight = 2.0; // the height of the antenna - - // TODO - // CommandLine cmd; - // cmd.AddValue ("vehicleSpeed", "The speed of the vehicle", speed); - // cmd.Parse (argc, argv); + std::string scenario = "V2V-Urban"; + + CommandLine cmd; + cmd.AddValue ("vehicleSpeed", "The speed of the vehicle", speed); + cmd.AddValue ("scenario", "set the vehicular scenario", scenario); + cmd.Parse (argc, argv); Config::SetDefault ("ns3::MmWaveSidelinkMac::UseAmc", BooleanValue (true)); Config::SetDefault ("ns3::MmWavePhyMacCommon::CenterFreq", DoubleValue (frequency)); + Config::SetDefault ("ns3::MmWaveVehicularHelper::Bandwidth", DoubleValue (bandwidth)); Config::SetDefault ("ns3::MmWaveVehicularHelper::Numerology", UintegerValue (numerology)); - Config::SetDefault ("ns3::MmWaveVehicularPropagationLossModel::ChannelCondition", StringValue ("l")); - Config::SetDefault ("ns3::MmWaveVehicularPropagationLossModel::Shadowing", BooleanValue (true)); - Config::SetDefault ("ns3::MmWaveVehicularSpectrumPropagationLossModel::UpdatePeriod", TimeValue (MilliSeconds (1))); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::AntennaElements", UintegerValue (4)); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::AntennaElementPattern", StringValue ("3GPP-V2V")); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::IsotropicAntennaElements", BooleanValue (true)); - Config::SetDefault ("ns3::MmWaveVehicularAntennaArrayModel::NumSectors", UintegerValue (2)); - + + Config::SetDefault ("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue (MilliSeconds (10))); + // create the nodes NodeContainer group1, group2; group1.Create (2); @@ -106,9 +105,8 @@ int main (int argc, char *argv[]) // create and configure the helper Ptr helper = CreateObject (); helper->SetNumerology (numerology); - helper->SetPropagationLossModelType ("ns3::MmWaveVehicularPropagationLossModel"); - helper->SetSpectrumPropagationLossModelType ("ns3::MmWaveVehicularSpectrumPropagationLossModel"); - // helper->SetSpectrumPropagationLossModelType ("ns3::FriisSpectrumPropagationLossModel"); + helper->SetNumerology (3); + helper->SetChannelModelType (scenario); NetDeviceContainer devs1 = helper->InstallMmWaveVehicularNetDevices (group1); NetDeviceContainer devs2 = helper->InstallMmWaveVehicularNetDevices (group2); @@ -124,6 +122,11 @@ int main (int argc, char *argv[]) ipv4.SetBase ("10.1.2.0", "255.255.255.0"); i = ipv4.Assign (devs2); + + // Mandatory to install buildings helper even if there are no buildings, + // otherwise V2V-Urban scenario does not work + BuildingsHelper::Install (group1); + BuildingsHelper::Install (group2); // connect the devices belonging to the same group helper->PairDevices(devs1); diff --git a/examples/wscript b/examples/wscript deleted file mode 100644 index fb7e336..0000000 --- a/examples/wscript +++ /dev/null @@ -1,18 +0,0 @@ -# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- - -def build(bld): - - obj = bld.create_ns3_program('vehicular-simple-one', ['millicar','core', 'propagation', 'spectrum', 'mmwave']) - obj.source = 'vehicular-simple-one.cc' - - obj = bld.create_ns3_program('vehicular-simple-two', ['millicar','core', 'propagation', 'spectrum', 'mmwave']) - obj.source = 'vehicular-simple-two.cc' - - obj = bld.create_ns3_program('vehicular-simple-three', ['millicar','core', 'propagation', 'spectrum', 'mmwave']) - obj.source = 'vehicular-simple-three.cc' - - obj = bld.create_ns3_program('vehicular-simple-four', ['millicar','core', 'propagation', 'spectrum', 'mmwave']) - obj.source = 'vehicular-simple-four.cc' - - obj = bld.create_ns3_program('mmwave-vehicular-link-adaptation-example', ['millicar']) - obj.source = 'mmwave-vehicular-link-adaptation-example.cc' diff --git a/helper/mmwave-vehicular-helper.cc b/helper/mmwave-vehicular-helper.cc index bb4dec7..f70f135 100644 --- a/helper/mmwave-vehicular-helper.cc +++ b/helper/mmwave-vehicular-helper.cc @@ -22,9 +22,12 @@ #include "ns3/double.h" #include "ns3/mmwave-vehicular-net-device.h" #include "ns3/internet-stack-helper.h" -#include "ns3/single-model-spectrum-channel.h" -#include "ns3/mmwave-vehicular-antenna-array-model.h" -#include "ns3/mmwave-vehicular-spectrum-propagation-loss-model.h" +#include "ns3/multi-model-spectrum-channel.h" +#include "ns3/three-gpp-spectrum-propagation-loss-model.h" +#include "ns3/three-gpp-v2v-propagation-loss-model.h" +#include "ns3/three-gpp-v2v-channel-condition-model.h" +#include "ns3/three-gpp-channel-model.h" +#include "ns3/mmwave-beamforming-model.h" #include "ns3/pointer.h" #include "ns3/config.h" @@ -54,27 +57,18 @@ MmWaveVehicularHelper::GetTypeId () TypeId ("ns3::MmWaveVehicularHelper") .SetParent () .AddConstructor () - .AddAttribute ("PropagationLossModel", - "The type of path-loss model to be used. " - "The allowed values for this attributes are the type names " - "of any class inheriting from ns3::PropagationLossModel.", - StringValue (""), - MakeStringAccessor (&MmWaveVehicularHelper::SetPropagationLossModelType), - MakeStringChecker ()) - .AddAttribute ("SpectrumPropagationLossModel", - "The type of fast fading model to be used. " - "The allowed values for this attributes are the type names " - "of any class inheriting from ns3::SpectrumPropagationLossModel.", - StringValue (""), - MakeStringAccessor (&MmWaveVehicularHelper::SetSpectrumPropagationLossModelType), - MakeStringChecker ()) - .AddAttribute ("PropagationDelayModel", - "The type of propagation delay model to be used. " - "The allowed values for this attributes are the type names " - "of any class inheriting from ns3::PropagationDelayModel.", - StringValue (""), - MakeStringAccessor (&MmWaveVehicularHelper::SetPropagationDelayModelType), + .AddAttribute ("BeamformingModel", + "The type of beamforming model to be used.", + StringValue ("ns3::MmWaveSvdBeamforming"), + MakeStringAccessor (&MmWaveVehicularHelper::SetBeamformingModelType), MakeStringChecker ()) + .AddAttribute ("ChannelModelType", + "The type of channel model to be used. " + "The allowed values for this attributes are V2V-Urban, V2V-Highway" + " and Ideal", + StringValue("V2V-Urban"), + MakeStringAccessor (&MmWaveVehicularHelper::SetChannelModelType), + MakeStringChecker()) .AddAttribute ("Numerology", "Numerology to use for the definition of the frame structure." "2 : subcarrier spacing will be set to 60 KHz" @@ -116,38 +110,52 @@ MmWaveVehicularHelper::DoInitialize () "Bandwidth", DoubleValue (m_bandwidth)); } - // create the channel - m_channel = CreateObject (); - if (!m_propagationLossModelType.empty ()) - { - ObjectFactory factory (m_propagationLossModelType); - m_channel->AddPropagationLossModel (factory.Create ()); - } - if (!m_spectrumPropagationLossModelType.empty ()) - { - ObjectFactory factory (m_spectrumPropagationLossModelType); - m_channel->AddSpectrumPropagationLossModel (factory.Create ()); - } - if (!m_propagationDelayModelType.empty ()) - { - ObjectFactory factory (m_propagationDelayModelType); - m_channel->SetPropagationDelayModel (factory.Create ()); - } + m_channel = CreateSpectrumChannel (m_channelModelType); +} - // 3GPP vehicular channel needs proper configuration - if (m_spectrumPropagationLossModelType == "ns3::MmWaveVehicularSpectrumPropagationLossModel") +Ptr +MmWaveVehicularHelper::CreateSpectrumChannel (std::string channelModelType) const +{ + Ptr channel = CreateObject (); + if (channelModelType == "V2V-Urban") { - Ptr threeGppSplm = DynamicCast (m_channel->GetSpectrumPropagationLossModel ()); - PointerValue plm; - m_channel->GetAttribute ("PropagationLossModel", plm); + Ptr ccm = CreateObject (); - Ptr pathloss = DynamicCast (plm.Get ()); - pathloss->SetFrequency (m_phyMacConfig->GetCenterFrequency()); + Ptr plm = CreateObject (); + plm->SetChannelConditionModel (ccm); + plm->SetFrequency (m_phyMacConfig->GetCenterFrequency()); + + Ptr splm = CreateObject (); + splm->SetChannelModelAttribute ("ChannelConditionModel", PointerValue (ccm)); + splm->SetChannelModelAttribute ("Frequency", DoubleValue(m_phyMacConfig->GetCenterFrequency())); + splm->SetChannelModelAttribute ("Scenario", StringValue ("V2V-Urban")); + channel->AddPropagationLossModel (plm); + channel->AddPhasedArraySpectrumPropagationLossModel (splm); + } + else if ("V2V-Highway") + { + Ptr ccm = CreateObject (); - threeGppSplm->SetPathlossModel (pathloss); // associate pathloss and fast fading models - threeGppSplm->SetFrequency (m_phyMacConfig->GetCenterFrequency()); // set correct value of frequency + Ptr plm = CreateObject (); + plm->SetChannelConditionModel (ccm); + plm->SetFrequency (m_phyMacConfig->GetCenterFrequency()); + Ptr splm = CreateObject (); + splm->SetChannelModelAttribute ("ChannelConditionModel", PointerValue (ccm)); + splm->SetChannelModelAttribute ("Frequency", DoubleValue(m_phyMacConfig->GetCenterFrequency())); + splm->SetChannelModelAttribute ("Scenario", StringValue ("V2V-Urban")); + channel->AddPropagationLossModel (plm); + channel->AddPhasedArraySpectrumPropagationLossModel (splm); } + else if ("Ideal") + { + // ideal channel, don't use any propagation loss model + } + else + { + NS_FATAL_ERROR ("Unknown channel model type"); + } + return channel; } void @@ -172,6 +180,13 @@ MmWaveVehicularHelper::SetNumerology (uint8_t index) m_numerologyIndex = index; } +void +MmWaveVehicularHelper::SetChannelModelType (std::string model) +{ + NS_LOG_FUNCTION (this); + m_channelModelType = model; +} + NetDeviceContainer MmWaveVehicularHelper::InstallMmWaveVehicularNetDevices (NodeContainer nodes) { @@ -200,17 +215,21 @@ Ptr MmWaveVehicularHelper::InstallSingleMmWaveVehicularNetDevice (Ptr node, uint16_t rnti) { NS_LOG_FUNCTION (this); - + // create the antenna - Ptr aam = CreateObject (); + Ptr aam = CreateObject (); // create and configure the tx spectrum phy Ptr ssp = CreateObject (); NS_ASSERT_MSG (node->GetObject (), "Missing mobility model"); ssp->SetMobility (node->GetObject ()); - ssp->SetAntenna (aam); NS_ASSERT_MSG (m_channel, "First create the channel"); ssp->SetChannel (m_channel); + ssp->SetAntenna (aam); + + // create the phy + NS_ASSERT_MSG (m_phyMacConfig, "First set the configuration parameters"); + Ptr phy = CreateObject (ssp, m_phyMacConfig); // add the spectrum phy to the spectrum channel m_channel->AddRx (ssp); @@ -220,9 +239,6 @@ MmWaveVehicularHelper::InstallSingleMmWaveVehicularNetDevice (Ptr node, ui pData->AddCallback (MakeCallback (&MmWaveSidelinkSpectrumPhy::UpdateSinrPerceived, ssp)); ssp->AddDataSinrChunkProcessor (pData); - // create the phy - NS_ASSERT_MSG (m_phyMacConfig, "First set the configuration parameters"); - Ptr phy = CreateObject (ssp, m_phyMacConfig); // connect the rx callback of the spectrum object to the sink ssp->SetPhyRxDataEndOkCallback (MakeCallback (&MmWaveSidelinkPhy::Receive, phy)); @@ -230,7 +246,7 @@ MmWaveVehicularHelper::InstallSingleMmWaveVehicularNetDevice (Ptr node, ui // connect the callback to report the SINR ssp->SetSidelinkSinrReportCallback (MakeCallback (&MmWaveSidelinkPhy::GenerateSinrReport, phy)); - if(m_phyTraceHelper != 0) + if(m_phyTraceHelper) { ssp->SetSidelinkSinrReportCallback (MakeCallback (&MmWaveVehicularTracesHelper::McsSinrCallback, m_phyTraceHelper)); } @@ -245,6 +261,7 @@ MmWaveVehicularHelper::InstallSingleMmWaveVehicularNetDevice (Ptr node, ui // create and configure the device Ptr device = CreateObject (phy, mac); + device->SetAntennaArray (aam); node->AddDevice (device); device->SetNode (node); ssp->SetDevice (device); @@ -253,10 +270,14 @@ MmWaveVehicularHelper::InstallSingleMmWaveVehicularNetDevice (Ptr node, ui mac->SetForwardUpCallback(MakeCallback(&MmWaveVehicularNetDevice::Receive, device)); // initialize the channel (if needed) - Ptr splm = DynamicCast (m_channel->GetSpectrumPropagationLossModel ()); - if (splm) - splm->AddDevice (device, aam); - + Ptr splm = DynamicCast (m_channel->GetPhasedArraySpectrumPropagationLossModel ()); + auto channelModel = splm->GetChannelModel(); + Ptr bfModel = m_bfModelFactory.Create (); + bfModel->SetAttributeFailSafe ("Device", PointerValue (device)); + bfModel->SetAttributeFailSafe ("Antenna", PointerValue (aam)); + bfModel->SetAttributeFailSafe ("ChannelModel", PointerValue (channelModel)); + ssp->SetBeamformingModel (bfModel); + return device; } @@ -278,7 +299,7 @@ MmWaveVehicularHelper::PairDevices (NetDeviceContainer devices) Ptr di = DynamicCast (*i); Ptr iNode = di->GetNode (); Ptr iNodeIpv4 = iNode->GetObject (); - NS_ASSERT_MSG (iNodeIpv4 != 0, "Nodes need to have IPv4 installed before pairing can be activated"); + NS_ASSERT_MSG (iNodeIpv4, "Nodes need to have IPv4 installed before pairing can be activated"); di->GetMac ()->SetSfAllocationInfo (pattern); // this is called ONCE for each NetDevice @@ -287,7 +308,7 @@ MmWaveVehicularHelper::PairDevices (NetDeviceContainer devices) Ptr dj = DynamicCast (*j); Ptr jNode = dj->GetNode (); Ptr jNodeIpv4 = jNode->GetObject (); - NS_ASSERT_MSG (jNodeIpv4 != 0, "Nodes need to have IPv4 installed before pairing can be activated"); + NS_ASSERT_MSG (jNodeIpv4, "Nodes need to have IPv4 installed before pairing can be activated"); // initialize the map of the devices int32_t interface = jNodeIpv4->GetInterfaceForDevice (dj); @@ -381,24 +402,10 @@ MmWaveVehicularHelper::CreateSchedulingPattern (NetDeviceContainer devices) } void -MmWaveVehicularHelper::SetPropagationLossModelType (std::string plm) +MmWaveVehicularHelper::SetBeamformingModelType (std::string type) { - NS_LOG_FUNCTION (this); - m_propagationLossModelType = plm; -} - -void -MmWaveVehicularHelper::SetSpectrumPropagationLossModelType (std::string splm) -{ - NS_LOG_FUNCTION (this); - m_spectrumPropagationLossModelType = splm; -} - -void -MmWaveVehicularHelper::SetPropagationDelayModelType (std::string pdm) -{ - NS_LOG_FUNCTION (this); - m_propagationDelayModelType = pdm; + NS_LOG_FUNCTION (this << type); + m_bfModelFactory = ObjectFactory (type); } void diff --git a/helper/mmwave-vehicular-helper.h b/helper/mmwave-vehicular-helper.h index 6c45dad..403c812 100644 --- a/helper/mmwave-vehicular-helper.h +++ b/helper/mmwave-vehicular-helper.h @@ -26,6 +26,7 @@ #include "ns3/spectrum-channel.h" #include "ns3/mmwave-phy-mac-common.h" #include "ns3/mmwave-vehicular-traces-helper.h" +#include "ns3/object-factory.h" namespace ns3 { @@ -72,24 +73,12 @@ class MmWaveVehicularHelper : public Object * \return a pointer to a MmWavePhyMacCommon object */ Ptr GetConfigurationParameters () const; - - /** - * Set the propagation loss model type - * \param plm the type id of the propagation loss model to use - */ - void SetPropagationLossModelType (std::string plm); - - /** - * Set the spectrum propagation loss model type - * \param splm the type id of the spectrum propagation loss model to use - */ - void SetSpectrumPropagationLossModelType (std::string splm); - + /** - * Set the propagation delay model type - * \param pdm the type id of the propagation delay model to use + * Set the beamforming delay model type + * \param pdm the type id of the beamforming model to use */ - void SetPropagationDelayModelType (std::string pdm); + void SetBeamformingModelType (std::string type); /** * Associate the devices in the container @@ -102,6 +91,12 @@ class MmWaveVehicularHelper : public Object * \param index numerology index, used to define PHY layer parameters */ void SetNumerology (uint8_t index); + + /** + * Configure the type of channel model to be used + * \param model string representing the channel model to be used + */ + void SetChannelModelType (std::string model); /** * Configure the scheduling pattern for a specific group of devices @@ -140,17 +135,23 @@ class MmWaveVehicularHelper : public Object * \return pointer to the installed NetDevice */ Ptr InstallSingleMmWaveVehicularNetDevice (Ptr n, uint16_t rnti); + + /** + * Create and configure the spectrum channel + * \param model string representing the type of channel model to be created + * \return pointer to the SpectrumChannel object + */ + Ptr CreateSpectrumChannel (std::string model) const; Ptr m_channel; //!< the SpectrumChannel Ptr m_phyMacConfig; //!< the configuration parameters uint16_t m_rntiCounter; //!< a counter to set the RNTIs uint8_t m_numerologyIndex; //!< numerology index double m_bandwidth; //!< system bandwidth - std::string m_propagationLossModelType; //!< the type id of the propagation loss model to be used - std::string m_spectrumPropagationLossModelType; //!< the type id of the spectrum propagation loss model to be used - std::string m_propagationDelayModelType; //!< the type id of the delay model to be used + std::string m_channelModelType; //!< the type of channel model to be used SchedulingPatternOption_t m_schedulingOpt; //!< the type of scheduling pattern policy to be adopted - + + ObjectFactory m_bfModelFactory; //!< beamforming model object factory Ptr m_phyTraceHelper; //!< Ptr to an helper for the physical layer traces }; diff --git a/model/mmwave-sidelink-spectrum-phy.cc b/model/mmwave-sidelink-spectrum-phy.cc index 1d02b23..a946551 100644 --- a/model/mmwave-sidelink-spectrum-phy.cc +++ b/model/mmwave-sidelink-spectrum-phy.cc @@ -138,7 +138,7 @@ MmWaveSidelinkSpectrumPhy::ResetSpectrumModel () void MmWaveSidelinkSpectrumPhy::SetDevice (Ptr d) { - NS_ABORT_MSG_IF(DynamicCast(d) == 0, + NS_ABORT_MSG_IF(!DynamicCast(d), "The MmWaveSidelinkSpectrumPhy only works with MmWaveVehicularNetDevices"); m_device = d; } @@ -173,14 +173,14 @@ MmWaveSidelinkSpectrumPhy::GetRxSpectrumModel () const return m_rxSpectrumModel; } -Ptr -MmWaveSidelinkSpectrumPhy::GetRxAntenna () const +Ptr +MmWaveSidelinkSpectrumPhy::GetAntenna () const { return m_antenna; } void -MmWaveSidelinkSpectrumPhy::SetAntenna (Ptr a) +MmWaveSidelinkSpectrumPhy::SetAntenna (Ptr a) { m_antenna = a; } @@ -235,7 +235,7 @@ MmWaveSidelinkSpectrumPhy::StartRx (Ptr params) Ptr mmwaveSidelinkParams = DynamicCast (params); - if (mmwaveSidelinkParams != 0) + if (mmwaveSidelinkParams) { // TODO remove dead code after testing that the following code can be // handled by the MmWaveSidelinkSpectrumPhy state machine @@ -497,7 +497,7 @@ MmWaveSidelinkSpectrumPhy::StartTxDataFrames (Ptr pb, txParams->psd = m_txPsd; txParams->packetBurst = pb; //txParams->ctrlMsgList = ctrlMsgList; - txParams->txAntenna = m_antenna; + txParams->txAntenna = nullptr; txParams->mcs = mcs; txParams->numSym = numSym; txParams->destinationRnti = destinationRnti; @@ -601,13 +601,22 @@ MmWaveSidelinkSpectrumPhy::ConfigureBeamforming (Ptr dev) { NS_LOG_FUNCTION (this); - Ptr antennaArray = DynamicCast (m_antenna); - if (antennaArray) - { - //TODO consider to update this in order to not recompute the beamforming - // vectors each time - antennaArray->SetBeamformingVectorPanelDevices (m_device, dev); - } + Ptr antenna; + + // test if device is a MmWaveVehicularNetDevice + Ptr vehicularDevice = DynamicCast (dev); + if (vehicularDevice) + { + antenna = vehicularDevice->GetAntennaArray (); + } + m_beamforming->SetBeamformingVectorForDevice (dev, antenna); +} + +void +MmWaveSidelinkSpectrumPhy::SetBeamformingModel (Ptr beamformingModel) +{ + NS_LOG_FUNCTION (this); + m_beamforming = beamformingModel; } void diff --git a/model/mmwave-sidelink-spectrum-phy.h b/model/mmwave-sidelink-spectrum-phy.h index 9d6cdfa..59091d0 100644 --- a/model/mmwave-sidelink-spectrum-phy.h +++ b/model/mmwave-sidelink-spectrum-phy.h @@ -41,6 +41,7 @@ #include "ns3/mmwave-interference.h" #include "ns3/mmwave-control-messages.h" #include +#include "ns3/mmwave-beamforming-model.h" namespace ns3 { @@ -157,18 +158,18 @@ class MmWaveSidelinkSpectrumPhy : public SpectrumPhy Ptr GetRxSpectrumModel () const; /** - * Get the AntennaModel used by the NetDevice for reception + * Get the antenna used by the NetDevice for reception * - * @return a Ptr to the AntennaModel used by the NetDevice for reception + * @return a Ptr to the antenna used by the NetDevice for reception */ - Ptr GetRxAntenna () const; + Ptr GetAntenna () const; /** * set the AntennaModel to be used * * \param a the Antenna Model */ - void SetAntenna (Ptr a); + void SetAntenna (Ptr a); void SetNoisePowerSpectralDensity (Ptr noisePsd); void SetTxPowerSpectralDensity (Ptr TxPsd); @@ -260,6 +261,13 @@ class MmWaveSidelinkSpectrumPhy : public SpectrumPhy */ void SetErrorModelType (TypeId errorModelType); + /** + * Configure the beamforming model to use + * \param beamformingModel object associated to the mmwave beamforming model + */ + void SetBeamformingModel (Ptr beamformingModel); + + private: /** * \brief Change state function @@ -289,7 +297,8 @@ class MmWaveSidelinkSpectrumPhy : public SpectrumPhy Time m_firstRxStart; ///< the first receive start Time m_firstRxDuration; ///< the first receive duration - Ptr m_antenna; ///< the antenna model + Ptr m_antenna; ///< the antenna model + Ptr m_beamforming; //!< used to compute the beamforming vector State m_state; ///< the state diff --git a/model/mmwave-sidelink-spectrum-signal-parameters.cc b/model/mmwave-sidelink-spectrum-signal-parameters.cc index 00afe23..0878406 100644 --- a/model/mmwave-sidelink-spectrum-signal-parameters.cc +++ b/model/mmwave-sidelink-spectrum-signal-parameters.cc @@ -55,17 +55,11 @@ MmWaveSidelinkSpectrumSignalParameters::MmWaveSidelinkSpectrumSignalParameters ( } Ptr -MmWaveSidelinkSpectrumSignalParameters::Copy () +MmWaveSidelinkSpectrumSignalParameters::Copy () const { NS_LOG_FUNCTION (this); - // Ideally we would use: - // return Copy (*this); - // but for some reason it doesn't work. Another alternative is - // return Copy (this); - // but it causes a double creation of the object, hence it is less efficient. - // The solution below is copied from the implementation of Copy<> (Ptr<>) in ptr.h - Ptr lssp (new MmWaveSidelinkSpectrumSignalParameters (*this), false); - return lssp; + + return Create (*this); } } diff --git a/model/mmwave-sidelink-spectrum-signal-parameters.h b/model/mmwave-sidelink-spectrum-signal-parameters.h index d96dd5d..8a4fc79 100644 --- a/model/mmwave-sidelink-spectrum-signal-parameters.h +++ b/model/mmwave-sidelink-spectrum-signal-parameters.h @@ -37,7 +37,7 @@ struct MmWaveSidelinkSpectrumSignalParameters : public SpectrumSignalParameters { // inherited from SpectrumSignalParameters - virtual Ptr Copy (); + virtual Ptr Copy () const; /** * default constructor diff --git a/model/mmwave-vehicular-antenna-array-model.cc b/model/mmwave-vehicular-antenna-array-model.cc index 18f1589..cf40bab 100644 --- a/model/mmwave-vehicular-antenna-array-model.cc +++ b/model/mmwave-vehicular-antenna-array-model.cc @@ -179,7 +179,7 @@ MmWaveVehicularAntennaArrayModel::SetBeamformingVectorPanelDevices (PtrGetNode ()->GetObject ()->GetPosition (); NS_LOG_INFO ("aPos: " << aPos); @@ -251,7 +251,7 @@ MmWaveVehicularAntennaArrayModel::SetBeamformingVectorPanel (complexVector_t ant { NS_LOG_FUNCTION (this << device << Simulator::Now ()); m_omniTx = false; - if (device != 0) + if (device) { auto iter = m_beamformingVectorPanelMap.find (device); if (iter != m_beamformingVectorPanelMap.end ()) diff --git a/model/mmwave-vehicular-net-device.cc b/model/mmwave-vehicular-net-device.cc index 5059bbe..198308f 100644 --- a/model/mmwave-vehicular-net-device.cc +++ b/model/mmwave-vehicular-net-device.cc @@ -409,6 +409,20 @@ MmWaveVehicularNetDevice::BidToLcid(const uint8_t bearerId) const return m_bid2lcid.find(bearerId)->second; } +void +MmWaveVehicularNetDevice::SetAntennaArray (Ptr antenna) +{ + NS_LOG_FUNCTION (this); + m_antenna = antenna; +} + +Ptr +MmWaveVehicularNetDevice::GetAntennaArray () const +{ + NS_LOG_FUNCTION (this); + return m_antenna; +} + } } diff --git a/model/mmwave-vehicular-net-device.h b/model/mmwave-vehicular-net-device.h index 32bf778..4afda77 100644 --- a/model/mmwave-vehicular-net-device.h +++ b/model/mmwave-vehicular-net-device.h @@ -24,6 +24,7 @@ #include "ns3/lte-pdcp.h" #include "ns3/lte-radio-bearer-info.h" #include "ns3/epc-tft-classifier.h" +#include #include "mmwave-sidelink-phy.h" #include "mmwave-sidelink-mac.h" @@ -179,6 +180,18 @@ class MmWaveVehicularNetDevice : public NetDevice * \param dest IP destination address */ void ActivateBearer (const uint8_t bearerId, const uint16_t destRnti, const Address& dest); + + /** + * \brief Set UniformPlanarArray object + * \param antenna antenna to mount on the device + */ + void SetAntennaArray (Ptr antenna); + + /** + * \brief Get a UniformPlanarArray object + * \return the antenna mounted on the devide + */ + Ptr GetAntennaArray () const; protected: NetDevice::ReceiveCallback m_rxCallback; //!< callback that is fired when a packet is received @@ -197,6 +210,8 @@ class MmWaveVehicularNetDevice : public NetDevice Ptr m_node; //!< pointer to the node associated to the NetDevice EpcTftClassifier m_tftClassifier; std::string m_rlcType; + + Ptr m_antenna; //!< antenna mounted on the device /** * Return the LCID associated to a certain bearer diff --git a/model/mmwave-vehicular-propagation-loss-model.cc b/model/mmwave-vehicular-propagation-loss-model.cc deleted file mode 100644 index 804ffd0..0000000 --- a/model/mmwave-vehicular-propagation-loss-model.cc +++ /dev/null @@ -1,564 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* -* Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) -* Copyright (c) 2015, NYU WIRELESS, Tandon School of Engineering, New York -* University -* Copyright (c) 2020 University of Padova, Dep. of Information Engineering, -* SIGNET lab. -* -* 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 -* -*/ - -#include "mmwave-vehicular-propagation-loss-model.h" -#include -#include "ns3/mobility-model.h" -#include "ns3/boolean.h" -#include "ns3/double.h" -#include "ns3/string.h" -#include "ns3/pointer.h" -#include -#include -#include - -namespace ns3 { - -namespace millicar { - -// ------------------------------------------------------------------------- // -NS_LOG_COMPONENT_DEFINE ("MmWaveVehicularPropagationLossModel"); - -NS_OBJECT_ENSURE_REGISTERED (MmWaveVehicularPropagationLossModel); - -static const double g_C = 299792458.0; // speed of light in vacuum - -TypeId -MmWaveVehicularPropagationLossModel::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::MmWaveVehicularPropagationLossModel") - .SetParent () - .AddConstructor () - .AddAttribute ("Frequency", - "Operating frequency in Hz.", - DoubleValue (0.0), - MakeDoubleAccessor (&MmWaveVehicularPropagationLossModel::SetFrequency, - &MmWaveVehicularPropagationLossModel::GetFrequency), - MakeDoubleChecker ()) - .AddAttribute ("MinLoss", - "The minimum value (dB) of the total loss, used at short ranges.", - DoubleValue (0.0), - MakeDoubleAccessor (&MmWaveVehicularPropagationLossModel::SetMinLoss, - &MmWaveVehicularPropagationLossModel::GetMinLoss), - MakeDoubleChecker ()) - .AddAttribute ("ChannelCondition", - "'l' for LOS, 'n' for NLOS, 'v' for NLOSv, 'a' for all", - StringValue ("a"), - MakeStringAccessor (&MmWaveVehicularPropagationLossModel::m_channelConditions), - MakeStringChecker ()) - .AddAttribute ("Scenario", - "The available channel scenarios are 'V2V-Highway', 'V2V-Urban', 'Extended-V2V-Highway','Extended-V2V-Urban'", - StringValue ("V2V-Highway"), - MakeStringAccessor (&MmWaveVehicularPropagationLossModel::m_scenario), - MakeStringChecker ()) - .AddAttribute ("Shadowing", - "Enable shadowing effect", - BooleanValue (true), - MakeBooleanAccessor (&MmWaveVehicularPropagationLossModel::m_shadowingEnabled), - MakeBooleanChecker ()) - .AddAttribute ("Type3Vehicles", - "The percentage of vehicles of type 3 (i.e. trucks) in the network", - DoubleValue (0.0), - MakeDoubleAccessor (&MmWaveVehicularPropagationLossModel::m_percType3Vehicles), - MakeDoubleChecker ()) - ; - return tid; -} - -MmWaveVehicularPropagationLossModel::MmWaveVehicularPropagationLossModel () -{ - m_channelConditionMap.clear (); - m_norVar = CreateObject (); - m_norVar->SetAttribute ("Mean", DoubleValue (0)); - m_norVar->SetAttribute ("Variance", DoubleValue (1)); - - m_logNorVar = CreateObject (); - m_logNorVar->SetAttribute ("Mu", DoubleValue (0)); - - m_uniformVar = CreateObject (); - m_uniformVar->SetAttribute ("Min", DoubleValue (0)); - m_uniformVar->SetAttribute ("Max", DoubleValue (1)); - -} - -void -MmWaveVehicularPropagationLossModel::SetMinLoss (double minLoss) -{ - m_minLoss = minLoss; -} -double -MmWaveVehicularPropagationLossModel::GetMinLoss (void) const -{ - return m_minLoss; -} - -void -MmWaveVehicularPropagationLossModel::SetFrequency (double freq) -{ - m_frequency = freq; - m_lambda = g_C / m_frequency; -} - -double -MmWaveVehicularPropagationLossModel::GetFrequency (void) const -{ - return m_frequency; -} - - -double -MmWaveVehicularPropagationLossModel::DoCalcRxPower (double txPowerDbm, - Ptr a, - Ptr b) const -{ - return (txPowerDbm - GetLoss (a, b)); -} - -double -MmWaveVehicularPropagationLossModel::GetLoss (Ptr deviceA, Ptr deviceB) const -{ - NS_ASSERT_MSG (m_frequency != 0.0, "Set the operating frequency first!"); - - Vector aPos = deviceA->GetPosition (); - Vector bPos = deviceB->GetPosition (); - double x = aPos.x - bPos.x; - double y = aPos.y - bPos.y; - double distance2D = sqrt (x * x + y * y); - double hA = aPos.z; - double hB = bPos.z; - - double distance3D = deviceA->GetDistanceFrom (deviceB); - - if (distance3D < 3 * m_lambda) - { - NS_LOG_UNCOND ("distance not within the far field region => inaccurate propagation loss value"); - } - if (distance3D <= 0) - { - return m_minLoss; - } - - channelConditionMap_t::const_iterator it; - it = m_channelConditionMap.find (std::make_pair (deviceA, deviceB)); - if (it == m_channelConditionMap.end ()) - { - channelCondition condition; - - if (m_channelConditions.compare ("l") == 0 ) - { - condition.m_channelCondition = 'l'; - NS_LOG_UNCOND (m_scenario << " scenario, channel condition is fixed to be " << condition.m_channelCondition << ", h_A=" << hA << ",h_B=" << hB); - } - else if (m_channelConditions.compare ("n") == 0) - { - condition.m_channelCondition = 'n'; - NS_LOG_UNCOND (m_scenario << " scenario, channel condition is fixed to be " << condition.m_channelCondition << ", h_A=" << hA << ",h_B=" << hB); - } - else if (m_channelConditions.compare ("v") == 0) - { - condition.m_channelCondition = 'v'; - NS_LOG_UNCOND (m_scenario << " scenario, channel condition is fixed to be " << condition.m_channelCondition << ", h_A=" << hA << ",h_B=" << hB); - } - else if (m_channelConditions.compare ("a") == 0) - { - double PRef = m_uniformVar->GetValue (); - double probLos, probnLos, probnLosv; - - if (m_scenario == "V2V-Highway") - { - double a, b, c; - a = 2.1013e-6; - b = - 0.002; - c = 1.0193; - - if (distance3D <= 475) - { - probLos = std::min(1.0, a * pow(distance3D, 2) + b * distance3D + c); - } - else - { - probLos = std::max(0.0, 0.54 - 0.001 * (distance3D - 475)); - } - - if (PRef <= probLos) - { - condition.m_channelCondition = 'l'; - } - else - { - condition.m_channelCondition = 'v'; - } - } - else if (m_scenario == "V2V-Urban") - { - probLos = std::min(1.0, 1.05 * exp(-0.0114 * distance3D)); - - if (PRef <= probLos) - { - condition.m_channelCondition = 'l'; - } - else - { - condition.m_channelCondition = 'v'; - } - } - else if (m_scenario == "Extended-V2V-Highway") - { - // As established from TR 37.885 we have to define - double aLOS, bLOS, cLOS = 1; - aLOS = 2.7e-6; - bLOS = - 0.0025; - - probLos = std::min(1.0, std::max(0.0, aLOS * pow(distance3D, 2) + bLOS * distance3D + cLOS)); - - double aNLOS, bNLOS, cNLOS = 0.015; - aNLOS = -3.7e-7; - bNLOS = 0.00061; - - probnLos = std::min(1.0, std::max(0.0, aNLOS * pow(distance3D, 2) + bNLOS * distance3D + cNLOS)); - - if (PRef <= probLos) - { - condition.m_channelCondition = 'l'; - } - else if (PRef <= probLos + probnLos) - { - condition.m_channelCondition = 'n'; - } - else - { - condition.m_channelCondition = 'v'; - } - } - else if (m_scenario == "Extended-V2V-Urban") - { - probLos = std::min(1.0, std::max(0.0, 0.8372 * exp (-0.0114*distance3D))); - probnLosv = std::min(1.0, std::max(0.0, 1/(0.0312*distance3D) * exp(- pow(log(distance3D) - 5.0063, 2) / 2.4544))); - - if (PRef <= probLos) - { - condition.m_channelCondition = 'l'; - } - else if (PRef <= probLos + probnLosv) - { - condition.m_channelCondition = 'v'; - } - else - { - condition.m_channelCondition = 'n'; - } - } - else - { - NS_FATAL_ERROR ("Unknown scenario"); - } - - NS_LOG_DEBUG (m_scenario << " scenario, 2D distance = " << distance2D << "m, Prob_LOS = " << probLos - << ", Prob_REF = " << PRef << ", the channel condition is " << condition.m_channelCondition << ", h_A=" << hA << ",h_B=" << hB); - } - else - { - NS_FATAL_ERROR ("Wrong channel condition configuration"); - } - - // assign a large negative value to identify initial transmission. - condition.m_shadowing = -1e6; - - std::pair ret; - ret = m_channelConditionMap.insert (std::make_pair (std::make_pair (deviceA, deviceB), condition)); - m_channelConditionMap.insert (std::make_pair (std::make_pair (deviceB, deviceA), condition)); - it = ret.first; - } - - double lossDb = 0; - double freqGHz = m_frequency / 1e9; - - double shadowingStd = 0; - double shadowingCorDistance = 0; - - if (m_scenario == "V2V-Highway") - { - // The shadowing standard deviation and decorrelation distance are - // specified in TR 36.885 Sec. A.1.4 - shadowingStd = 3.0; - shadowingCorDistance = 25.0; - - switch ((*it).second.m_channelCondition) - { - case 'l': - { - lossDb = 32.4 + 20 * log10 (distance3D) + 20 * log10 (freqGHz); - break; - } - case 'v': - { - double additionalLoss = GetAdditionalNlosVLoss (distance3D, hA, hB); - lossDb = 32.4 + 20 * log10 (distance3D) + 20 * log10 (freqGHz) + additionalLoss; - break; - } - case 'n': - { - lossDb = 36.85 + 30 * log10 (distance3D) + 18.9 * log10 (freqGHz); - break; - } - default: - NS_FATAL_ERROR ("Programming Error."); - - } - } - else if (m_scenario == "V2V-Urban") - { - switch ((*it).second.m_channelCondition) - { - case 'l': - { - lossDb = 38.77 + 16.7 * log10 (distance3D) + 18.2 * log10 (freqGHz); - - // The shadowing standard deviation and decorrelation distance are - // specified in TR 36.885 Sec. A.1.4 - shadowingStd = 3.0; - shadowingCorDistance = 10.0; - break; - } - case 'v': - { - double additionalLoss = GetAdditionalNlosVLoss (distance3D, hA, hB); - - lossDb = 38.77 + 16.7 * log10 (distance3D) + 18.2 * log10 (freqGHz) + additionalLoss; - break; - - } - case 'n': - { - lossDb = 36.85 + 30 * log10 (distance3D) + 18.9 * log10 (freqGHz); - - // The shadowing standard deviation and decorrelation distance are - // specified in TR 36.885 Sec. A.1.4 - shadowingStd = 4.0; - shadowingCorDistance = 10.0; - break; - } - default: - NS_FATAL_ERROR ("Programming Error."); - - } - } - else if (m_scenario == "Extended-V2V-Highway") - { - switch ((*it).second.m_channelCondition) - { - case 'l': - { - lossDb = 32.4 + 20 * log10 (distance3D) + 20 * log10 (freqGHz); - - shadowingStd = 3.0; - // The extended model does not specify the decorrelation distance. I - // assume the one specified by TR 36.885 - shadowingCorDistance = 25.0; - break; - } - case 'v': - { - double additionalLoss = GetAdditionalNlosVLoss (distance3D, hA, hB); - - lossDb = 32.4 + 20 * log10 (distance3D) + 20 * log10 (freqGHz) + additionalLoss; - break; - } - case 'n': - { - lossDb = 36.85 + 30 * log10 (distance3D) + 18.9 * log10 (freqGHz); - shadowingStd = 4.0; - // The extended model does not specify the decorrelation distance. I - // assume the one specified by TR 36.885 - shadowingCorDistance = 25.0; - break; - } - default: - NS_FATAL_ERROR ("Programming Error."); - } - } - else if (m_scenario == "Extended-V2V-Urban") - { - switch ((*it).second.m_channelCondition) - { - case 'l': - { - lossDb = 38.77 + 16.7 * log10 (distance3D) + 18.2 * log10 (freqGHz); - shadowingStd = 3.0; - // The extended model does not specify the decorrelation distance. I - // assume the one specified by TR 36.885 - shadowingCorDistance = 10.0; - break; - } - case 'v': - { - double additionalLoss = GetAdditionalNlosVLoss (distance3D, hA, hB); - - lossDb = 38.77 + 16.7 * log10 (distance3D) + 18.2 * log10 (freqGHz) + additionalLoss; - break; - } - case 'n': - { - lossDb = 36.85 + 30 * log10 (distance3D) + 18.9 * log10 (freqGHz); - shadowingStd = 4.0; - // The extended model does not specify the decorrelation distance. I - // assume the one specified by TR 36.885 - shadowingCorDistance = 10.0; - break; - } - default: - NS_FATAL_ERROR ("Programming Error."); - } - } - else - { - NS_FATAL_ERROR ("Unknown channel scenario"); - } - - if (m_shadowingEnabled) - { - - channelCondition cond; - cond = (*it).second; - - //The first transmission the shadowing is initialized as -1e6, - //we perform this if check to identify the first transmission. - m_logNorVar->SetAttribute ("Sigma", DoubleValue (shadowingStd)); - - if ((*it).second.m_shadowing < -1e5) - { - cond.m_shadowing = m_norVar->GetValue () * shadowingStd; - } - else - { - double deltaX = aPos.x - (*it).second.m_position.x; - double deltaY = aPos.y - (*it).second.m_position.y; - double disDiff = sqrt (deltaX * deltaX + deltaY * deltaY); - double R = exp (-1 * disDiff / shadowingCorDistance); - - cond.m_shadowing = R * (*it).second.m_shadowing + sqrt (1 - R * R) * m_norVar->GetValue () * shadowingStd; - } - - lossDb += cond.m_shadowing; - cond.m_position = deviceA->GetPosition (); - UpdateConditionMap (deviceA,deviceB,cond); - } - - return std::max (lossDb, m_minLoss); -} - -double -MmWaveVehicularPropagationLossModel::GetAdditionalNlosVLoss (double distance3D, double hA, double hB) const -{ - // From TR 37.885 v15.2.0 - // When a V2V link is in NLOSv, additional vehicle blockage loss is - // added as follows: - // 1. The blocker height is the vehicle height which is randomly selected - // out of the three vehicle types according to the portion of the vehicle - // types in the simulated scenario. - double additionalLoss = 0; - double blockerHeight = 0; - double mu_a = 0; - double sigma_a = 0; - double randomValue = m_uniformVar->GetValue () * 3.0; - if (randomValue < m_percType3Vehicles) - { - // vehicles of type 3 have height 3 meters - blockerHeight = 3.0; - } - else - { - // vehicles of type 1 and 2 have height 1.6 meters - blockerHeight = 1.6; - } - - // The additional blockage loss is max {0 dB, a log-normal random variable} - if (std::min (hA, hB) > blockerHeight) - { - // Case 1: Minimum antenna height value of TX and RX > Blocker height - additionalLoss = 0; - } - else if (std::max (hA, hB) < blockerHeight) - { - // Case 2: Maximum antenna height value of TX and RX < Blocker height - mu_a = 9.0 + std::max (0.0, 15 * log10 (distance3D) - 41.0); - sigma_a = 4.5; - // Pay attention to the ambiguous definition of the parameters. - // Vehicular TR 37.885 defines mu_a and sigma_a as the mean and standard deviation of the log-normal random variable. - // ns-3's RNG considers mu and sigma as specific parameters of the log-normal distribution, while the mean and standard deviation are evaluated separately. - m_logNorVar->SetAttribute ("Mu", DoubleValue (log10(pow(mu_a,2) / sqrt(pow(sigma_a,2) + pow(mu_a,2))))); - m_logNorVar->SetAttribute ("Sigma", DoubleValue (sqrt(log10(pow(sigma_a,2) / pow(mu_a,2) + 1)))); - additionalLoss = std::max(0.0, m_logNorVar->GetValue()); - } - else - { - // Case 3: Otherwise - mu_a = 5.0 + std::max (0.0, 15 * log10 (distance3D) - 41.0); - sigma_a = 4.0; - // Pay attention to the ambiguous definition of the parameters. - // Vehicular TR 37.885 defines mu_a and sigma_a as the mean and standard deviation of the log-normal random variable. - // ns-3's RNG considers mu and sigma as specific parameters of the log-normal distribution, while the mean and standard deviation are evaluated separately. - m_logNorVar->SetAttribute ("Mu", DoubleValue (log10(pow(mu_a,2) / sqrt(pow(sigma_a,2) + pow(mu_a,2))))); - m_logNorVar->SetAttribute ("Sigma", DoubleValue (sqrt(log10(pow(sigma_a,2) / pow(mu_a,2) + 1)))); - additionalLoss = std::max(0.0, m_logNorVar->GetValue()); - } - - return additionalLoss; -} - -int64_t -MmWaveVehicularPropagationLossModel::DoAssignStreams (int64_t stream) -{ - return 0; -} - -void -MmWaveVehicularPropagationLossModel::UpdateConditionMap (Ptr a, Ptr b, channelCondition cond) const -{ - m_channelConditionMap[std::make_pair (a,b)] = cond; - m_channelConditionMap[std::make_pair (b,a)] = cond; - -} - -char -MmWaveVehicularPropagationLossModel::GetChannelCondition (Ptr a, Ptr b) -{ - channelConditionMap_t::const_iterator it; - it = m_channelConditionMap.find (std::make_pair (a,b)); - if (it == m_channelConditionMap.end ()) - { - NS_FATAL_ERROR ("Cannot find the link in the map"); - } - return (*it).second.m_channelCondition; - -} - -std::string -MmWaveVehicularPropagationLossModel::GetScenario () -{ - return m_scenario; -} - -} // namespace millicar - -} // namespace ns3 diff --git a/model/mmwave-vehicular-propagation-loss-model.h b/model/mmwave-vehicular-propagation-loss-model.h deleted file mode 100644 index 97d9050..0000000 --- a/model/mmwave-vehicular-propagation-loss-model.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* -* Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) -* Copyright (c) 2015, NYU WIRELESS, Tandon School of Engineering, New York -* University -* Copyright (c) 2020 University of Padova, Dep. of Information Engineering, -* SIGNET lab. -* -* 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 -* -*/ - -#ifndef MMWAVE_VEHICULAR_PROPAGATION_LOSS_MODEL_H_ -#define MMWAVE_VEHICULAR_PROPAGATION_LOSS_MODEL_H_ - -#include "ns3/propagation-loss-model.h" -#include "ns3/object.h" -#include "ns3/random-variable-stream.h" -#include -#include -#include - -/* - * This propagation loss model for vehicular communications has been implemented based on the 3GPP TR 37.885 v15.2.0 (2019-01). - * - * 3rd Generation Partnership Project; - * Technical Specification Group Radio Access Network; - * (Release 14) - * - * */ - -namespace ns3 { - -namespace millicar { - -struct channelCondition -{ - char m_channelCondition; - double m_shadowing; - Vector m_position; -}; - -// map store the path loss scenario(LOS,NLOS,OUTAGE) of each propagation channel -typedef std::map< std::pair< Ptr, Ptr >, channelCondition> channelConditionMap_t; - -class MmWaveVehicularPropagationLossModel : public PropagationLossModel -{ - public: - - static TypeId GetTypeId (void); - MmWaveVehicularPropagationLossModel (); - - /** - * \param minLoss the minimum loss (dB) - * - * no matter how short the distance, the total propagation loss (in - * dB) will always be greater or equal than this value - */ - void SetMinLoss (double minLoss); - - /** - * \return the minimum loss. - */ - double GetMinLoss (void) const; - - /** - * \param freq the operating frequency (Hz) - */ - void SetFrequency (double freq); - - /** - * \returns the current frequency (Hz) - */ - double GetFrequency (void) const; - - char GetChannelCondition (Ptr a, Ptr b); - - std::string GetScenario (); - - double GetLoss (Ptr a, Ptr b) const; - - private: - - MmWaveVehicularPropagationLossModel (const MmWaveVehicularPropagationLossModel &o); - MmWaveVehicularPropagationLossModel & operator = (const MmWaveVehicularPropagationLossModel &o); - - virtual double DoCalcRxPower (double txPowerDbm, - Ptr a, - Ptr b) const; - virtual int64_t DoAssignStreams (int64_t stream); - void UpdateConditionMap (Ptr a, Ptr b, channelCondition cond) const; - - /** - * \param distance3D: the 3D distance between tx and rx - * \param hA: the height of device A - * \param hB: the height of device B - * - * \returns the additional NLOSv loss - */ - double GetAdditionalNlosVLoss (double distance3D, double hA, double hB) const; - - double m_frequency; - double m_lambda; - double m_minLoss; - mutable channelConditionMap_t m_channelConditionMap; - std::string m_channelConditions; - std::string m_scenario; - bool m_optionNlosEnabled; - Ptr m_norVar; - Ptr m_logNorVar; - Ptr m_uniformVar; - bool m_shadowingEnabled; - double m_percType3Vehicles; -}; - -} // namespace millicar - -} // namespace ns3 - -#endif diff --git a/model/mmwave-vehicular-spectrum-propagation-loss-model.cc b/model/mmwave-vehicular-spectrum-propagation-loss-model.cc deleted file mode 100644 index d32adec..0000000 --- a/model/mmwave-vehicular-spectrum-propagation-loss-model.cc +++ /dev/null @@ -1,2499 +0,0 @@ - -/* -* Copyright (c) 2015, NYU WIRELESS, Tandon School of Engineering, New York -* University -* Copyright (c) 2016, 2018, 2020 University of Padova, Dep. of Information -* Engineering, SIGNET lab. -* -* 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 -* -*/ - -#include "mmwave-vehicular-spectrum-propagation-loss-model.h" -#include -#include -#include -#include -#include -#include -#include // std::default_random_engine -#include -#include - -namespace ns3 { - -namespace millicar { - -NS_LOG_COMPONENT_DEFINE ("MmWaveVehicularSpectrumPropagationLossModel"); - -NS_OBJECT_ENSURE_REGISTERED (MmWaveVehicularSpectrumPropagationLossModel); - -//Table 7.5-3: Ray offset angles within a cluster, given for rms angle spread normalized to 1. -static const double offSetAlpha[20] = { - 0.0447,-0.0447,0.1413,-0.1413,0.2492,-0.2492,0.3715,-0.3715,0.5129,-0.5129,0.6797,-0.6797,0.8844,-0.8844,1.1481,-1.1481,1.5195,-1.5195,2.1551,-2.1551 -}; - -/* - * The cross correlation matrix is constructed according to table 7.5-6. - * All the square root matrix is being generated using the Cholesky decomposition - * and following the order of [SF,K,DS,ASD,ASA,ZSD,ZSA]. - * The parameter K is ignored in NLOS. - * - * The Matlab file to generate the matrices can be found in the mmwave/model/BeamFormingMatrix/SqrtMatrix.m - * */ - -static const double sqrtC_UMi_LOS[7][7] = { - {1, 0, 0, 0, 0, 0, 0}, - {0.5, 0.866025, 0, 0, 0, 0, 0}, - {-0.4, -0.57735, 0.711805, 0, 0, 0, 0}, - {-0.5, 0.057735, 0.468293, 0.726201, 0, 0, 0}, - {-0.4, -0.11547, 0.805464, -0.23482, 0.350363, 0, 0}, - {0, 0, 0, 0.688514, 0.461454, 0.559471, 0}, - {0, 0, 0.280976, 0.231921, -0.490509, 0.11916, 0.782603}, -}; - -static const double sqrtC_UMi_NLOS[6][6] = { - {1, 0, 0, 0, 0, 0}, - {-0.7, 0.714143, 0, 0, 0, 0}, - {0, 0, 1, 0, 0, 0}, - {-0.4, 0.168034, 0, 0.90098, 0, 0}, - {0, -0.70014, 0.5, 0.130577, 0.4927, 0}, - {0, 0, 0.5, 0.221981, -0.566238, 0.616522}, -}; - -static const double oxygen_loss[17][2] = { - {52.0e9, 0.0}, - {53.0e9, 1.0}, - {54.0e9, 2.2}, - {55.0e9, 4.0}, - {56.0e9, 6.6}, - {57.0e9, 9.7}, - {58.0e9, 12.6}, - {59.0e9, 14.6}, - {60.0e9, 15.0}, - {61.0e9, 14.6}, - {62.0e9, 14.3}, - {63.0e9, 10.5}, - {64.0e9, 6.8}, - {65.0e9, 3.9}, - {66.0e9, 1.9}, - {67.0e9, 1.0}, - {68.0e9, 0.0} -}; - -MmWaveVehicularSpectrumPropagationLossModel::MmWaveVehicularSpectrumPropagationLossModel () -{ - m_uniformRv = CreateObject (); - m_uniformRvBlockage = CreateObject (); - m_expRv = CreateObject (); - m_normalRv = CreateObject (); - m_normalRv->SetAttribute ("Mean", DoubleValue (0)); - m_normalRv->SetAttribute ("Variance", DoubleValue (1)); - m_normalRvBlockage = CreateObject (); - m_normalRvBlockage->SetAttribute ("Mean", DoubleValue (0)); - m_normalRvBlockage->SetAttribute ("Variance", DoubleValue (1)); -} - -TypeId -MmWaveVehicularSpectrumPropagationLossModel::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::MmWaveVehicularSpectrumPropagationLossModel") - .SetParent () - .AddConstructor () - .AddAttribute ("Frequency", - "Operating frequency in Hz", - DoubleValue (0.0), - MakeDoubleAccessor (&MmWaveVehicularSpectrumPropagationLossModel::SetFrequency, - &MmWaveVehicularSpectrumPropagationLossModel::GetFrequency), - MakeDoubleChecker ()) - .AddAttribute ("UpdatePeriod", - "Enable spatially-consistent UT mobility modeling procedure A, the update period unit is in ms, set to 0 ms to disable update", - TimeValue (MilliSeconds (1)), - MakeTimeAccessor (&MmWaveVehicularSpectrumPropagationLossModel::m_updatePeriod), - MakeTimeChecker ()) - .AddAttribute ("Blockage", - "Enable blockage model A (sec 7.6.4.1)", - BooleanValue (false), - MakeBooleanAccessor (&MmWaveVehicularSpectrumPropagationLossModel::m_blockage), - MakeBooleanChecker ()) - .AddAttribute ("NumNonselfBlocking", - "number of non-self-blocking regions", - IntegerValue (4), - MakeIntegerAccessor (&MmWaveVehicularSpectrumPropagationLossModel::m_numNonSelfBloking), - MakeIntegerChecker ()) - .AddAttribute ("BlockerSpeed", - "The speed of moving blockers, the unit is m/s", - DoubleValue (1), - MakeDoubleAccessor (&MmWaveVehicularSpectrumPropagationLossModel::m_blockerSpeed), - MakeDoubleChecker ()) - .AddAttribute ("PortraitMode", - "true for portrait mode, false for landscape mode", - BooleanValue (true), - MakeBooleanAccessor (&MmWaveVehicularSpectrumPropagationLossModel::m_portraitMode), - MakeBooleanChecker ()) - .AddAttribute ("OxygenAbsorption", - "true for considering oxygen absortion, false for not considering it", - BooleanValue (true), - MakeBooleanAccessor (&MmWaveVehicularSpectrumPropagationLossModel::m_oxygenAbsorption), - MakeBooleanChecker ()) - .AddAttribute ("O2I", - "Outdoor to Indoor channel state", - BooleanValue (false), - MakeBooleanAccessor (&MmWaveVehicularSpectrumPropagationLossModel::m_o2i), - MakeBooleanChecker ()) - ; - return tid; -} - -MmWaveVehicularSpectrumPropagationLossModel::~MmWaveVehicularSpectrumPropagationLossModel () -{ - -} - -void -MmWaveVehicularSpectrumPropagationLossModel::DoDispose () -{ - NS_LOG_FUNCTION (this); -} - -void -MmWaveVehicularSpectrumPropagationLossModel::AddDevice (Ptr dev, Ptr antenna) -{ - NS_ASSERT_MSG (m_deviceAntennaMap.find (dev) == m_deviceAntennaMap.end (), "Device is already present in the map"); - m_deviceAntennaMap.insert (std::pair , Ptr> (dev, antenna)); -} - -Ptr -MmWaveVehicularSpectrumPropagationLossModel::DoCalcRxPowerSpectralDensity (Ptr txPsd, - Ptr a, - Ptr b) const -{ - NS_LOG_FUNCTION (this); - - // check if the frequency is correctly set - NS_ASSERT_MSG (m_frequency != 0.0, "Set the operating frequency first!"); - - Ptr rxPsd = Copy (txPsd); - - Ptr txDevice = a->GetObject ()->GetDevice (0); - Ptr rxDevice = b->GetObject ()->GetDevice (0); - - Vector locUT = b->GetPosition (); // TODO change this - - // retrieve the antenna of the tx device - NS_ASSERT_MSG (m_deviceAntennaMap.find (txDevice) != m_deviceAntennaMap.end (), "Antenna not found for device " << txDevice); - Ptr txAntennaArray = m_deviceAntennaMap.at (txDevice); - NS_LOG_DEBUG ("tx dev " << txDevice << " antenna " << txAntennaArray); - - // retrieve the antenna of the rx device - NS_ASSERT_MSG (m_deviceAntennaMap.find (txDevice) != m_deviceAntennaMap.end (), "Antenna not found for device " << rxDevice); - Ptr rxAntennaArray = m_deviceAntennaMap.at (rxDevice); - NS_LOG_DEBUG ("rx dev " << rxDevice << " antenna " << rxAntennaArray); - - /* txAntennaNum[0]-number of vertical antenna elements - * txAntennaNum[1]-number of horizontal antenna elements*/ - // NOTE: only squared antenna arrays are currently supported - uint16_t txAntennaNum[2]; - txAntennaNum[0] = sqrt (txAntennaArray->GetTotNoArrayElements ()); - txAntennaNum[1] = txAntennaNum[0]; - NS_LOG_DEBUG ("number of tx antenna elements " << txAntennaNum[0] << " x " << txAntennaNum[1]); - - uint16_t rxAntennaNum[2]; - rxAntennaNum[0] = sqrt (rxAntennaArray->GetTotNoArrayElements ()); - rxAntennaNum[1] = rxAntennaNum[0]; - NS_LOG_DEBUG ("number of rx antenna elements " << rxAntennaNum[0] << " x " << rxAntennaNum[1]); - - if (txAntennaArray->IsOmniTx () || rxAntennaArray->IsOmniTx () ) - { - NS_LOG_LOGIC ("Omni transmission, do nothing."); - return rxPsd; - } - - NS_ASSERT_MSG (a->GetDistanceFrom (b) != 0, "The position of tx and rx devices cannot be the same"); - - Vector rxSpeed = b->GetVelocity (); - Vector txSpeed = a->GetVelocity (); - Vector relativeSpeed (rxSpeed.x - txSpeed.x,rxSpeed.y - txSpeed.y,rxSpeed.z - txSpeed.z); - - key_t key = std::make_pair (txDevice,rxDevice); - key_t keyReverse = std::make_pair (rxDevice,txDevice); - - std::map< key_t, Ptr >::iterator it = m_channelMap.find (key); - std::map< key_t, Ptr >::iterator itReverse = m_channelMap.find (keyReverse); - - Ptr channelParams; - - //Step 2: Assign propagation condition (LOS/NLOS). - - char condition; - if (DynamicCast (m_3gppPathloss) != 0) - { - condition = m_3gppPathloss->GetObject () - ->GetChannelCondition (a->GetObject (),b->GetObject ()); - } - // else if (DynamicCast (m_3gppPathloss) != 0) - // { - // condition = m_3gppPathloss->GetObject () - // ->GetChannelCondition (a->GetObject (),b->GetObject ()); - // } - else - { - NS_FATAL_ERROR ("unknown pathloss model"); - } - - bool o2i = m_o2i; // In the current implementation the O2I state is manually - // configured. - - //Every m_updatedPeriod, the channel matrix is deleted and a consistent channel update is triggered. - //When there is a LOS/NLOS switch, a new uncorrelated channel is created. - //Therefore, LOS/NLOS condition of updating is always consistent with the previous channel. - - //I only update the forward channel. - if ((it == m_channelMap.end () && itReverse == m_channelMap.end ()) - || (it != m_channelMap.end () && it->second->m_channel.size () == 0) - || (it != m_channelMap.end () && it->second->m_condition != condition) - || (itReverse != m_channelMap.end () && itReverse->second->m_channel.size () == 0) - || (itReverse != m_channelMap.end () && itReverse->second->m_condition != condition)) - { - NS_LOG_INFO ("Update or create the forward channel"); - NS_LOG_LOGIC ("it == m_channelMap.end () " << (it == m_channelMap.end ())); - NS_LOG_LOGIC ("itReverse == m_channelMap.end () " << (itReverse == m_channelMap.end ())); - NS_LOG_LOGIC ("it->second->m_channel.size() == 0 " << (it->second->m_channel.size () == 0)); - NS_LOG_LOGIC ("it->second->m_condition != condition" << (it->second->m_condition != condition)); - - //Step 1: The parameters are configured in the example code. - /*make sure txAngle rxAngle exist, i.e., the position of tx and rx cannot be the same*/ - Angles txAngle (b->GetPosition (), a->GetPosition ()); - Angles rxAngle (a->GetPosition (), b->GetPosition ()); - NS_LOG_DEBUG ("txAngle " << txAngle.GetAzimuth () << " " << txAngle.GetInclination ()); - NS_LOG_DEBUG ("rxAngle " << rxAngle.GetAzimuth () << " " << rxAngle.GetInclination ()); - - txAngle.SetAzimuth (txAngle.GetAzimuth () - txAntennaArray->GetOffset ()); //adjustment of the angles due to multi-sector consideration - NS_LOG_DEBUG ("txAngle with offset PHI " << txAngle.GetAzimuth ()); - rxAngle.SetAzimuth (rxAngle.GetAzimuth () - rxAntennaArray->GetOffset ()); - NS_LOG_DEBUG ("rxAngle with offset PHI " << rxAngle.GetAzimuth ()); - - //Step 2: Assign propagation condition (LOS/NLOS). - //los, o2i condition is computed above. - - //Step 3: The propagation loss is handled in the mmWavePropagationLossModel class. - - double x = a->GetPosition ().x - b->GetPosition ().x; - double y = a->GetPosition ().y - b->GetPosition ().y; - double distance2D = sqrt (x * x + y * y); - double hTx = a->GetPosition ().z; - double hRx = b->GetPosition ().z; - - //Draw parameters from table 7.5-6 and 7.5-7 to 7.5-10. - Ptr table3gpp = Get3gppTable (condition, o2i, hTx, hRx, distance2D); - - // Step 4-11 are performed in function GetNewChannel() - if ((it == m_channelMap.end () && itReverse == m_channelMap.end ()) - || (it != m_channelMap.end () && it->second->m_channel.size () == 0)) - { - //delete the channel parameter to cause the channel to be updated again. - //The m_updatePeriod can be configured to be relatively large in order to disable updates. - if (m_updatePeriod.GetMilliSeconds () > 0) - { - NS_LOG_INFO ("Time " << Simulator::Now ().GetSeconds () << " schedule delete for a " << a->GetPosition () << " b " << b->GetPosition () - << " m_updatePeriod " << m_updatePeriod.GetSeconds ()); - Simulator::Schedule (m_updatePeriod, &MmWaveVehicularSpectrumPropagationLossModel::DeleteChannel,this,a,b); - } - } - - double distance3D = a->GetDistanceFrom (b); - - bool channelUpdate = false; - if (it != m_channelMap.end () && it->second->m_channel.size () == 0) - { - //if the channel map is not empty, we only update the channel. - NS_LOG_DEBUG ("Update forward channel consistently between MobilityModel " << a << " " << b); - it->second->m_locUT = locUT; - it->second->m_condition = condition; - it->second->m_o2i = o2i; - channelParams = UpdateChannel (it->second, table3gpp, txAntennaArray, rxAntennaArray, - txAntennaNum, rxAntennaNum, rxAngle, txAngle); - it->second->m_dis3D = distance3D; - it->second->m_dis2D = distance2D; - it->second->m_speed = relativeSpeed; - it->second->m_generatedTime = Now (); - it->second->m_preLocUT = locUT; - channelUpdate = true; - } - else - { - //if the channel map is empty, we create a new channel. - NS_LOG_INFO ("Create new channel"); - channelParams = GetNewChannel (table3gpp, locUT, condition, o2i, txAntennaArray, rxAntennaArray, - txAntennaNum, rxAntennaNum, rxAngle, txAngle, relativeSpeed, distance2D, distance3D); - } - - NS_LOG_DEBUG (" --- UPDATE BF VECTOR and LONGTERM vectors --- for new or update? " << channelUpdate); - - // insert the channelParams in the map - m_channelMap[key] = channelParams; - } - else if (itReverse == m_channelMap.end ()) // Find channel matrix in the forward link - { - channelParams = (*it).second; - NS_LOG_DEBUG ("No need to update the channel"); - } - else // Find channel matrix in the Reverse link - { - channelParams = (*itReverse).second; - - NS_LOG_DEBUG ("No need to update the channel"); - } - - // for now, store these BF vectors so that CalLongTerm can use them - channelParams->m_txW = txAntennaArray->GetBeamformingVectorPanel (); - channelParams->m_rxW = rxAntennaArray->GetBeamformingVectorPanel (); - - // call CalLongTerm, and get the longTerm params - auto longTerm = CalLongTerm (channelParams); - - channelParams->m_longTerm = longTerm; - - Ptr bfPsd = CalBeamformingGain (rxPsd, channelParams, longTerm, rxSpeed, txSpeed); - - SpectrumValue bfGain = (*bfPsd) / (*rxPsd); - uint8_t nbands = bfGain.GetSpectrumModel ()->GetNumBands (); - - NS_LOG_DEBUG ("****** BF gain == " << Sum (bfGain) / nbands << " RX PSD " << Sum (*rxPsd) / nbands - << " a pos " << a->GetPosition () - << " a antenna ID " << txAntennaArray->GetPlanesId () - << " b pos " << b->GetPosition () - << " b antenna ID " << rxAntennaArray->GetPlanesId ()); - return bfPsd; -} - -Ptr -MmWaveVehicularSpectrumPropagationLossModel::CalBeamformingGain (Ptr txPsd, Ptr params, - complexVector_t longTerm, Vector rxSpeed, Vector txSpeed) const -{ - NS_LOG_FUNCTION (this); - - Ptr tempPsd = Copy (txPsd); - - //NS_ASSERT_MSG (params->m_delay.size()==params->m_channel.at(0).at(0).size(), "the cluster number of channel and delay spread should be the same"); - //NS_ASSERT_MSG (params->m_txW.size()==params->m_channel.at(0).size(), "the tx antenna size of channel and antenna weights should be the same"); - //NS_ASSERT_MSG (params->m_rxW.size()==params->m_channel.size(), "the rx antenna size of channel and antenna weights should be the same"); - //NS_ASSERT_MSG (params->m_angle.at(0).size()==params->m_channel.at(0).at(0).size(), "the cluster number of channel and AOA should be the same"); - //NS_ASSERT_MSG (params->m_angle.at(1).size()==params->m_channel.at(0).at(0).size(), "the cluster number of channel and ZOA should be the same"); - - //channel[rx][tx][cluster] - uint8_t numCluster = params->m_numCluster; - //uint8_t txAntenna = params->m_txW.size(); - //uint8_t rxAntenna = params->m_rxW.size(); - //the update of Doppler is simplified by only taking the center angle of each cluster in to consideration. - Values::iterator vit = tempPsd->ValuesBegin (); - Bands::const_iterator sbit = tempPsd->ConstBandsBegin(); // sub band iterator - - double slotTime = Simulator::Now ().GetSeconds (); - complexVector_t doppler; - for (uint8_t cIndex = 0; cIndex < numCluster; cIndex++) - { - - double alpha = 0.0, D = 0.0, vScatt = 0.0, delayedPathsTerm = 0.0; // parameters used to evaluate Doppler effect in delayed paths as described in p. 32 of TR 37.885 - - if(cIndex != 0) - { - if(m_scenario == "V2V-Highway" || m_scenario == "Extended-V2V-Highway") - { - vScatt = 140/3.6; // maximum speed in highway scenario, converted in m/s to be consistent with other speed measures - } - else if (m_scenario == "V2V-Urban" || m_scenario == "Extended-V2V-Urban") - { - vScatt = 60/3.6; // maximum speed in urban scenario, converted in m/s to be consistent with other speed measures - } - D = m_uniformRv->GetValue(-vScatt, vScatt); - alpha = m_uniformRv->GetValue(0, 1); - delayedPathsTerm = 2 * alpha * D; - } - - //cluster angle angle[direction][n],where, direction = 0(aoa), 1(zoa). - // - double temp_doppler = 2 * M_PI * ((sin (params->m_angle.at (ZOA_INDEX).at (cIndex) * M_PI / 180) * cos (params->m_angle.at (AOA_INDEX).at (cIndex) * M_PI / 180) * rxSpeed.x - + sin (params->m_angle.at (ZOA_INDEX).at (cIndex) * M_PI / 180) * sin (params->m_angle.at (AOA_INDEX).at (cIndex) * M_PI / 180) * rxSpeed.y - + cos (params->m_angle.at (ZOA_INDEX).at (cIndex) * M_PI / 180) * rxSpeed.z) - + (sin (params->m_angle.at (ZOD_INDEX).at (cIndex) * M_PI / 180) * cos (params->m_angle.at (AOD_INDEX).at (cIndex) * M_PI / 180) * txSpeed.x - + sin (params->m_angle.at (ZOD_INDEX).at (cIndex) * M_PI / 180) * sin (params->m_angle.at (AOD_INDEX).at (cIndex) * M_PI / 180) * txSpeed.y - + cos (params->m_angle.at (ZOD_INDEX).at (cIndex) * M_PI / 180) * txSpeed.z) + delayedPathsTerm) - * slotTime * m_frequency / 3e8; - doppler.push_back (exp (std::complex (0, temp_doppler))); - - } - - while (vit != tempPsd->ValuesEnd ()) - { - std::complex subsbandGain (0.0,0.0); - if ((*vit) != 0.00) - { - double fsb = (*sbit).fc; - for (uint8_t cIndex = 0; cIndex < numCluster; cIndex++) - { - double delay = -2 * M_PI * fsb * (params->m_delay.at (cIndex)); - double tauDelta = 0.0; - - if(cIndex != 0) - { - tauDelta = params->m_tauDelta; // when in LOS condition, tau_{\Delta} is equal to zero. - } - - if(!m_oxygenAbsorption) - { - subsbandGain = subsbandGain + longTerm.at (cIndex) * doppler.at (cIndex) * exp (std::complex (0, delay)); - } - else - { - subsbandGain = subsbandGain + longTerm.at (cIndex) * doppler.at (cIndex) * exp (std::complex (0, delay)) / GetOxygenLoss(fsb, params->m_dis3D, params->m_delay.at (cIndex), tauDelta); - } - - } - *vit = (*vit) * (norm (subsbandGain)); - } - vit++; - sbit++; - } - return tempPsd; -} - - -double -MmWaveVehicularSpectrumPropagationLossModel::GetOxygenLoss (double f, double dist3D, double tau, double tauDelta) const -{ - NS_LOG_FUNCTION (this << f << dist3D << tau << tauDelta); - double alpha = 0.0, loss = 0.0; - - if(f > oxygen_loss[0][0] && f < oxygen_loss[16][0]) - { - for (uint8_t idx = 1; idx <= 15; idx++) - { - if ( f > oxygen_loss[idx-1][0] && f <= oxygen_loss[idx][0] ) - { - // interpolation of the oxygen_loss table - alpha = (oxygen_loss[idx][1] - oxygen_loss[idx-1][1])/(oxygen_loss[idx][0] - oxygen_loss[idx-1][0])*(f - oxygen_loss[idx-1][0]) + oxygen_loss[idx-1][1]; - loss = alpha / 1e3 * (dist3D + 3e8 * (tau + tauDelta)); - NS_LOG_DEBUG ("f (subband) " << f << " alpha " << alpha << " dB/km loss " << loss << " dB"); - } - } - } - - return pow(10.0, loss/10); // need to obtain the linear term, since in TR 38.901 the formula is in dB - -} - -void -MmWaveVehicularSpectrumPropagationLossModel::SetPathlossModel (Ptr pathloss) -{ - m_3gppPathloss = pathloss; - if (DynamicCast (m_3gppPathloss) != 0) - { - m_scenario = m_3gppPathloss->GetObject ()->GetScenario (); - } - // else if (DynamicCast (m_3gppPathloss) != 0) - // { - // m_scenario = m_3gppPathloss->GetObject ()->GetScenario (); - // } - else - { - NS_FATAL_ERROR ("unknown pathloss model"); - } -} - - -complexVector_t -MmWaveVehicularSpectrumPropagationLossModel::CalLongTerm (Ptr params) const -{ - uint16_t txAntenna = params->m_txW.size (); - uint16_t rxAntenna = params->m_rxW.size (); - - NS_LOG_DEBUG ("CalLongTerm with txAntenna " << (uint16_t)txAntenna << " rxAntenna " << (uint16_t)rxAntenna); - //store the long term part to reduce computation load - //only the small scale fading is need to be updated if the large scale parameters and antenna weights remain unchanged. - complexVector_t longTerm; - uint8_t numCluster = params->m_numCluster; - - for (uint8_t cIndex = 0; cIndex < numCluster; cIndex++) - { - std::complex txSum (0,0); - for (uint16_t txIndex = 0; txIndex < txAntenna; txIndex++) - { - std::complex rxSum (0,0); - for (uint16_t rxIndex = 0; rxIndex < rxAntenna; rxIndex++) - { - rxSum = rxSum + params->m_rxW.at (rxIndex) * params->m_channel.at (rxIndex).at (txIndex).at (cIndex); - } - txSum = txSum + params->m_txW.at (txIndex) * rxSum; - } - longTerm.push_back (txSum); - } - return longTerm; - -} - -Ptr -MmWaveVehicularSpectrumPropagationLossModel::Get3gppTable (char condition, bool o2i, double hBS, double hUT, double distance2D) const -{ - double fcGHz = m_frequency / 1e9; - Ptr table3gpp = CreateObject (); - // table3gpp includes the following parameters: - // numOfCluster, raysPerCluster, uLgDS, sigLgDS, uLgASD, sigLgASD, - // uLgASA, sigLgASA, uLgZSA, sigLgZSA, uLgZSD, sigLgZSD, offsetZOD, - // cDS, cASD, cASA, cZSA, uK, sigK, rTau, shadowingStd - - //In NLOS case, parameter uK and sigK are not used and 0 is passed into the SetParams() function. - if (m_scenario == "V2V-Urban" || m_scenario == "Extended-V2V-Urban") - { - if (condition == 'l') - { - table3gpp->SetParams (12, // number of clusters - 20, // number of rays per cluster - -0.2 * log10 (1 + fcGHz) - 7.5, // mu DS - 0.1, // sigma DS - -0.1 * log10 (1 + fcGHz) + 1.6, // AOD spread mu - 0.1, // AOD spread sigma - -0.1 * log10 (1 + fcGHz) + 1.6, // AOA spread mu - 0.1, // AOA spread sigma - -0.1 * log10 (1 + fcGHz) + 0.73, // ZOA spread mu - -0.04 * log10 (1 + fcGHz) + 0.34, // ZOA spread sigma - -0.1 * log10 (1 + fcGHz) + 0.73, // ZOD spread mu - -0.04 * log10 (1 + fcGHz) + 0.34, // ZOD spread sigma - 0, // ZOD offset - 5, // cluster DS - 17, // cluster ASD - 17, // cluster ASA - 7, // cluster ZSA - 3.48, // K-factor mu - 2, // K-factor sigma - 3, // delay scaling parameter - 4); // per cluster shadowing std - - for (uint8_t row = 0; row < 7; row++) - { - for (uint8_t column = 0; column < 7; column++) - { - table3gpp->m_sqrtC[row][column] = sqrtC_UMi_LOS[row][column]; - } - } - } - else if (condition == 'n') - { - table3gpp->SetParams (19, // number of clusters - 20, // number of rays per cluster - -0.3 * log10 (1 + fcGHz) - 7, // mu DS - 0.28, // sigma DS - -0.08 * log10 (1 + fcGHz) + 1.81, // AOD spread mu - 0.05 * log10 (1 + fcGHz) + 0.3, // AOD spread sigma - -0.08 * log10 (1 + fcGHz) + 1.81, // AOA spread mu - 0.05 * log10 (1 + fcGHz) + 0.3, // AOA spread sigma - -0.04 * log10 (1 + fcGHz) + 0.92, // ZOA spread mu - -0.07 * log10 (1 + fcGHz) + 0.41, // ZOA spread sigma - -0.04 * log10 (1 + fcGHz) + 0.92, // ZOD spread mu - -0.07 * log10 (1 + fcGHz) + 0.41, // ZOD spread sigma - 0, // ZOD offset - 11, // cluster DS - 22, // cluster ASD - 22, // cluster ASA - 7, // cluster ZSA - 0, // K-factor mu NOTE this value is NA - 0, // K-factor sigma NOTE this value is NA - 2.1, // delay scaling parameter - 4); // per cluster shadowing std - - for (uint8_t row = 0; row < 6; row++) - { - for (uint8_t column = 0; column < 6; column++) - { - table3gpp->m_sqrtC[row][column] = sqrtC_UMi_NLOS[row][column]; - } - } - } - else if (condition == 'v') - { - table3gpp->SetParams (19, // number of clusters - 20, // number of rays per cluster - -0.4 * log10 (1 + fcGHz) - 7, // mu DS - 0.1, // sigma DS - -0.1 * log10 (1 + fcGHz) + 1.7, // AOD spread mu - 0.1, // AOD spread sigma - -0.1 * log10 (1 + fcGHz) + 1.7, // AOA spread mu - 0.1, // AOA spread sigma - -0.04 * log10 (1 + fcGHz) + 0.92, // ZOA spread mu - -0.07 * log10 (1 + fcGHz) + 0.41, // ZOA spread sigma - -0.04 * log10 (1 + fcGHz) + 0.92, // ZOD spread mu - -0.07 * log10 (1 + fcGHz) + 0.41, // ZOD spread sigma - 0, // ZOD offset - 11, // cluster DS - 22, // cluster ASD - 22, // cluster ASA - 7, // cluster ZSA - 0, // K-factor mu - 4.5, // K-factor sigma - 2.1, // delay scaling parameter - 4); // per cluster shadowing std - - for (uint8_t row = 0; row < 7; row++) - { - for (uint8_t column = 0; column < 7; column++) - { - table3gpp->m_sqrtC[row][column] = sqrtC_UMi_LOS[row][column]; - } - } - } - else - { - NS_FATAL_ERROR ("Unknown channel condition"); - } - } - else if (m_scenario == "V2V-Highway" || m_scenario == "Extended-V2V-Highway") - { - if (condition == 'l') - { - table3gpp->SetParams (12, // number of clusters - 20, // number of rays per cluster - -8.3, // mu DS - 0.2, // sigma DS - 1.4, // AOD spread mu - 0.1, // AOD spread sigma - 1.4, // AOA spread mu - 0.1, // AOA spread sigma - -0.1 * log10 (1 + fcGHz) + 0.73, // ZOA spread mu - -0.04 * log10 (1 + fcGHz) + 0.34, // ZOA spread sigma - -0.1 * log10 (1 + fcGHz) + 0.73, // ZOD spread mu - -0.04 * log10 (1 + fcGHz) + 0.34, // ZOD spread sigma - 0, // ZOD offset - 5, // cluster DS - 17, // cluster ASD - 17, // cluster ASA - 7, // cluster ZSA - 9, // K-factor mu - 3.5, // K-factor sigma - 3, // delay scaling parameter - 4); // per cluster shadowing std - - for (uint8_t row = 0; row < 7; row++) - { - for (uint8_t column = 0; column < 7; column++) - { - table3gpp->m_sqrtC[row][column] = sqrtC_UMi_LOS[row][column]; - } - } - } - else if (condition == 'v') - { - table3gpp->SetParams (19, // number of clusters - 20, // number of rays per cluster - -8.3, // mu DS - 0.3, // sigma DS - 1.5, // AOD spread mu - 0.1, // AOD spread sigma - 1.5, // AOA spread mu - 0.1, // AOA spread sigma - -0.04 * log10 (1 + fcGHz) + 0.92, // ZOA spread mu - -0.07 * log10 (1 + fcGHz) + 0.41, // ZOA spread sigma - -0.04 * log10 (1 + fcGHz) + 0.92, // ZOD spread mu - -0.07 * log10 (1 + fcGHz) + 0.41, // ZOD spread sigma - 0, // ZOD offset - 11, // cluster DS - 22, // cluster ASD - 22, // cluster ASA - 7, // cluster ZSA - 0, // K-factor mu - 4.5, // K-factor sigma - 2.1, // delay scaling parameter - 4); // per cluster shadowing std - - for (uint8_t row = 0; row < 7; row++) - { - for (uint8_t column = 0; column < 7; column++) - { - table3gpp->m_sqrtC[row][column] = sqrtC_UMi_LOS[row][column]; - } - } - } - else if (condition == 'n') - { - NS_LOG_WARN ("The fast fading parameters for the NLOS condition in the (Extended)-V2V-Highway scenario are not defined in TR 37.885, use the ones defined in TDoc R1-1803671 instead"); - table3gpp->SetParams (19, // number of clusters - 20, // number of rays per cluster - -7.66, // mu DS - -7.62, // sigma DS - 1.32, // AOD spread mu - 0.77, // AOD spread sigma - 1.32, // AOA spread mu - 0.77, // AOA spread sigma - -0.04 * log10 (1 + fcGHz) + 0.92, // ZOA spread mu - -0.07 * log10 (1 + fcGHz) + 0.41, // ZOA spread sigma - 0, // ZOD spread mu NOTE this is not defined in the TDoc - 0, // ZOD spread sigma NOTE this is not defined in the TDoc - 0, // ZOD offset - 0, // cluster DS NOTE this is not defined in the TDoc - 10, // cluster ASD - 22, // cluster ASA - 7, // cluster ZSA - 0, // K-factor mu NOTE this is not defined in the TDoc - 0, // K-factor sigma NOTE this is not defined in the TDoc - 2.1, // delay scaling parameter - 4); // per cluster shadowing std - - for (uint8_t row = 0; row < 6; row++) - { - for (uint8_t column = 0; column < 6; column++) - { - table3gpp->m_sqrtC[row][column] = sqrtC_UMi_NLOS[row][column]; - } - } - } - else - { - NS_FATAL_ERROR ("Unknown channel condition"); - } - - } - else - { - //Note that the InH-ShoppingMall scenario is not given in the table 7.5-6 - NS_FATAL_ERROR ("unkonw scenarios"); - } - - return table3gpp; - -} - -void -MmWaveVehicularSpectrumPropagationLossModel::DeleteChannel (Ptr a, Ptr b) const -{ - NS_LOG_FUNCTION (this); - Ptr dev1 = a->GetObject ()->GetDevice (0); - Ptr dev2 = b->GetObject ()->GetDevice (0); - NS_LOG_INFO ("a position " << a->GetPosition () << " b " << b->GetPosition ()); - Ptr params = m_channelMap.find (std::make_pair (dev1,dev2))->second; - NS_LOG_INFO ("params " << params); - NS_LOG_INFO ("params m_channel size" << params->m_channel.size ()); - NS_ASSERT_MSG (m_channelMap.find (std::make_pair (dev1,dev2)) != m_channelMap.end (), "Channel not found"); - params->m_channel.clear (); - m_channelMap[std::make_pair (dev1,dev2)] = params; -} - -Ptr -MmWaveVehicularSpectrumPropagationLossModel::GetNewChannel (Ptr table3gpp, Vector locUT, char condition, bool o2i, - Ptr txAntenna, Ptr rxAntenna, - uint16_t *txAntennaNum, uint16_t *rxAntennaNum, Angles &rxAngle, Angles &txAngle, - Vector speed, double dis2D, double dis3D) const -{ - uint8_t numOfCluster = table3gpp->m_numOfCluster; - uint8_t raysPerCluster = table3gpp->m_raysPerCluster; - Ptr channelParams = Create (); - //for new channel, the previous and current location is the same. - channelParams->m_preLocUT = locUT; - channelParams->m_locUT = locUT; - channelParams->m_condition = condition; - channelParams->m_o2i = o2i; - channelParams->m_generatedTime = Now (); - channelParams->m_speed = speed; - channelParams->m_dis2D = dis2D; - channelParams->m_dis3D = dis3D; - //Step 4: Generate large scale parameters. All LSPS are uncorrelated. - doubleVector_t LSPsIndep, LSPs; - uint8_t paramNum; - if (condition == 'l') - { - paramNum = 7; - } - else - { - paramNum = 6; - } - //Generate paramNum independent LSPs. - for (uint8_t iter = 0; iter < paramNum; iter++) - { - LSPsIndep.push_back (m_normalRv->GetValue ()); - } - for (uint8_t row = 0; row < paramNum; row++) - { - double temp = 0; - for (uint8_t column = 0; column < paramNum; column++) - { - temp += table3gpp->m_sqrtC[row][column] * LSPsIndep.at (column); - } - LSPs.push_back (temp); - } - - /*std::cout << "LSPsIndep:"; - for (uint8_t i = 0; i < paramNum; i++) - { - std::cout <m_sigK + table3gpp->m_uK; - DS = pow (10, LSPs.at (2) * table3gpp->m_sigLgDS + table3gpp->m_uLgDS); - ASD = pow (10, LSPs.at (3) * table3gpp->m_sigLgASD + table3gpp->m_uLgASD); - ASA = pow (10, LSPs.at (4) * table3gpp->m_sigLgASA + table3gpp->m_uLgASA); - ZSD = pow (10, LSPs.at (5) * table3gpp->m_sigLgZSD + table3gpp->m_uLgZSD); - ZSA = pow (10, LSPs.at (6) * table3gpp->m_sigLgZSA + table3gpp->m_uLgZSA); - } - else - { - DS = pow (10, LSPs.at (1) * table3gpp->m_sigLgDS + table3gpp->m_uLgDS); - ASD = pow (10, LSPs.at (2) * table3gpp->m_sigLgASD + table3gpp->m_uLgASD); - ASA = pow (10, LSPs.at (3) * table3gpp->m_sigLgASA + table3gpp->m_uLgASA); - ZSD = pow (10, LSPs.at (4) * table3gpp->m_sigLgZSD + table3gpp->m_uLgZSD); - ZSA = pow (10, LSPs.at (5) * table3gpp->m_sigLgZSA + table3gpp->m_uLgZSA); - - } - ASD = std::min (ASD, 104.0); - ASA = std::min (ASA, 104.0); - ZSD = std::min (ZSD, 52.0); - ZSA = std::min (ZSA, 52.0); - - channelParams->m_DS = DS; - channelParams->m_K = K_factor; - - NS_LOG_INFO ("K-factor=" << K_factor << ",DS=" << DS << ", ASD=" << ASD << ", ASA=" << ASA << ", ZSD=" << ZSD << ", ZSA=" << ZSA); - - //Step 5: Generate Delays. - doubleVector_t clusterDelay; - double minTau = 100.0; - for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++) - { - double tau = -1*table3gpp->m_rTau*DS*log (m_uniformRv->GetValue (0,1)); //(7.5-1) - if (minTau > tau) - { - minTau = tau; - } - clusterDelay.push_back (tau); - } - channelParams->m_tauDelta = minTau; - for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++) - { - clusterDelay.at (cIndex) -= minTau; - } - std::sort (clusterDelay.begin (), clusterDelay.end ()); //(7.5-2) - - /* since the scaled Los delays are not to be used in cluster power generation, - * we will generate cluster power first and resume to compute Los cluster delay later.*/ - - //Step 6: Generate cluster powers. - doubleVector_t clusterPower; - double powerSum = 0; - for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++) - { - double power = exp (-1 * clusterDelay.at (cIndex) * (table3gpp->m_rTau - 1) / table3gpp->m_rTau / DS) * - pow (10,-1 * m_normalRv->GetValue () * table3gpp->m_shadowingStd / 10); //(7.5-5) - powerSum += power; - clusterPower.push_back (power); - } - double powerMax = 0; - - for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++) - { - clusterPower.at (cIndex) = clusterPower.at (cIndex) / powerSum; //(7.5-6) - } - - doubleVector_t clusterPowerForAngles; // this power is only for equation (7.5-9) and (7.5-14), not for (7.5-22) - if (condition == 'l') - { - double K_linear = pow (10,K_factor / 10); - - for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++) - { - if (cIndex == 0) - { - clusterPowerForAngles.push_back (clusterPower.at (cIndex) / (1 + K_linear) + K_linear / (1 + K_linear)); //(7.5-8) - } - else - { - clusterPowerForAngles.push_back (clusterPower.at (cIndex) / (1 + K_linear)); //(7.5-8) - } - if (powerMax < clusterPowerForAngles.at (cIndex)) - { - powerMax = clusterPowerForAngles.at (cIndex); - } - } - } - else - { - for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++) - { - clusterPowerForAngles.push_back (clusterPower.at (cIndex)); //(7.5-6) - if (powerMax < clusterPowerForAngles.at (cIndex)) - { - powerMax = clusterPowerForAngles.at (cIndex); - } - } - } - - //remove clusters with less than -25 dB power compared to the maxim cluster power; - //double thresh = pow(10,-2.5); - double thresh = 0.0032; - for (uint8_t cIndex = numOfCluster; cIndex > 0; cIndex--) - { - if (clusterPowerForAngles.at (cIndex - 1) < thresh * powerMax ) - { - clusterPowerForAngles.erase (clusterPowerForAngles.begin () + cIndex - 1); - clusterPower.erase (clusterPower.begin () + cIndex - 1); - clusterDelay.erase (clusterDelay.begin () + cIndex - 1); - } - } - uint8_t numReducedCluster = clusterPower.size (); - - channelParams->m_numCluster = numReducedCluster; - // Resume step 5 to compute the delay for LoS condition. - if (condition == 'l') - { - double C_tau = 0.7705 - 0.0433 * K_factor + 2e-4 * pow (K_factor,2) + 17e-6 * pow (K_factor,3); //(7.5-3) - for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++) - { - clusterDelay.at (cIndex) = clusterDelay.at (cIndex) / C_tau; //(7.5-4) - } - } - - /*for (uint8_t i = 0; i < clusterPowerForAngles.size(); i++) - { - std::cout <GetValue (0,1) < 0.5) - { - Xn = -1; - } - clusterAoa.at (cIndex) = clusterAoa.at (cIndex) * Xn + (m_normalRv->GetValue () * ASA / 7) + rxAngle.GetAzimuth () * 180 / M_PI; //(7.5-11) - clusterAod.at (cIndex) = clusterAod.at (cIndex) * Xn + (m_normalRv->GetValue () * ASD / 7) + txAngle.GetAzimuth () * 180 / M_PI; - if (o2i) - { - clusterZoa.at (cIndex) = clusterZoa.at (cIndex) * Xn + (m_normalRv->GetValue () * ZSA / 7) + 90; //(7.5-16) - } - else - { - clusterZoa.at (cIndex) = clusterZoa.at (cIndex) * Xn + (m_normalRv->GetValue () * ZSA / 7) + rxAngle.GetInclination () * 180 / M_PI; //(7.5-16) - } - clusterZod.at (cIndex) = clusterZod.at (cIndex) * Xn + (m_normalRv->GetValue () * ZSD / 7) + txAngle.GetInclination () * 180 / M_PI + table3gpp->m_offsetZOD; //(7.5-19) - - } - - if (condition == 'l') - { - //The 7.5-12 can be rewrite as Theta_n,ZOA = Theta_n,ZOA - (Theta_1,ZOA - Theta_LOS,ZOA) = Theta_n,ZOA - diffZOA, - //Similar as AOD, ZSA and ZSD. - double diffAoa = clusterAoa.at (0) - rxAngle.GetAzimuth () * 180 / M_PI; - double diffAod = clusterAod.at (0) - txAngle.GetAzimuth () * 180 / M_PI; - double diffZsa = clusterZoa.at (0) - rxAngle.GetInclination () * 180 / M_PI; - double diffZsd = clusterZod.at (0) - txAngle.GetInclination () * 180 / M_PI; - - for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++) - { - clusterAoa.at (cIndex) -= diffAoa; //(7.5-12) - clusterAod.at (cIndex) -= diffAod; - clusterZoa.at (cIndex) -= diffZsa; //(7.5-17) - clusterZod.at (cIndex) -= diffZsd; - - } - } - - double rayAoa_radian[numReducedCluster][raysPerCluster]; //rayAoa_radian[n][m], where n is cluster index, m is ray index - double rayAod_radian[numReducedCluster][raysPerCluster]; //rayAod_radian[n][m], where n is cluster index, m is ray index - double rayZoa_radian[numReducedCluster][raysPerCluster]; //rayZoa_radian[n][m], where n is cluster index, m is ray index - double rayZod_radian[numReducedCluster][raysPerCluster]; //rayZod_radian[n][m], where n is cluster index, m is ray index - - for (uint8_t nInd = 0; nInd < numReducedCluster; nInd++) - { - for (uint8_t mInd = 0; mInd < raysPerCluster; mInd++) - { - double tempAoa = clusterAoa.at (nInd) + table3gpp->m_cASA * offSetAlpha[mInd]; //(7.5-13) - while (tempAoa > 360) - { - tempAoa -= 360; - } - - while (tempAoa < 0) - { - tempAoa += 360; - - } - NS_ASSERT_MSG (tempAoa >= 0 && tempAoa <= 360, "the AOA should be the range of [0,360]"); - rayAoa_radian[nInd][mInd] = tempAoa * M_PI / 180; - - double tempAod = clusterAod.at (nInd) + table3gpp->m_cASD * offSetAlpha[mInd]; - while (tempAod > 360) - { - tempAod -= 360; - } - - while (tempAod < 0) - { - tempAod += 360; - } - NS_ASSERT_MSG (tempAod >= 0 && tempAod <= 360, "the AOD should be the range of [0,360]"); - rayAod_radian[nInd][mInd] = tempAod * M_PI / 180; - - double tempZoa = clusterZoa.at (nInd) + table3gpp->m_cZSA * offSetAlpha[mInd]; //(7.5-18) - - while (tempZoa > 360) - { - tempZoa -= 360; - } - - while (tempZoa < 0) - { - tempZoa += 360; - } - - if (tempZoa > 180) - { - tempZoa = 360 - tempZoa; - } - - NS_ASSERT_MSG (tempZoa >= 0&&tempZoa <= 180, "the ZOA should be the range of [0,180]"); - rayZoa_radian[nInd][mInd] = tempZoa * M_PI / 180; - - double tempZod = clusterZod.at (nInd) + 0.375 * pow (10,table3gpp->m_uLgZSD) * offSetAlpha[mInd]; //(7.5-20) - - while (tempZod > 360) - { - tempZod -= 360; - } - - while (tempZod < 0) - { - tempZod += 360; - } - if (tempZod > 180) - { - tempZod = 360 - tempZod; - } - NS_ASSERT_MSG (tempZod >= 0&&tempZod <= 180, "the ZOD should be the range of [0,180]"); - rayZod_radian[nInd][mInd] = tempZod * M_PI / 180; - } - } - doubleVector_t angle_degree; - double sizeTemp = clusterZoa.size (); - for (uint8_t ind = 0; ind < 4; ind++) - { - switch (ind) - { - case 0: - angle_degree = clusterAoa; - break; - case 1: - angle_degree = clusterZoa; - break; - case 2: - angle_degree = clusterAod; - break; - case 3: - angle_degree = clusterZod; - break; - default: - NS_FATAL_ERROR ("Programming Error"); - } - - for (uint8_t nIndex = 0; nIndex < sizeTemp; nIndex++) - { - while (angle_degree[nIndex] > 360) - { - angle_degree[nIndex] -= 360; - } - - while (angle_degree[nIndex] < 0) - { - angle_degree[nIndex] += 360; - } - - if (ind == 1 || ind == 3) - { - if (angle_degree[nIndex] > 180) - { - angle_degree[nIndex] = 360 - angle_degree[nIndex]; - } - } - } - switch (ind) - { - case 0: - clusterAoa = angle_degree; - break; - case 1: - clusterZoa = angle_degree; - break; - case 2: - clusterAod = angle_degree; - break; - case 3: - clusterZod = angle_degree; - break; - default: - NS_FATAL_ERROR ("Programming Error"); - } - } - - doubleVector_t attenuation_dB; - if (m_blockage) - { - attenuation_dB = CalAttenuationOfBlockage (channelParams, clusterAoa, clusterZoa); - for (uint8_t cInd = 0; cInd < numReducedCluster; cInd++) - { - clusterPower.at (cInd) = clusterPower.at (cInd) / pow (10,attenuation_dB.at (cInd) / 10); - } - } - else - { - attenuation_dB.push_back (0); - } - - /*std::cout << "BlockedPower:"; - for (uint8_t i = 0; i < numReducedCluster; i++) - { - std::cout <GetValue (-1 * M_PI, M_PI)); - } - clusterPhase.push_back (temp); - } - double losPhase = m_uniformRv->GetValue (-1 * M_PI, M_PI); - channelParams->m_clusterPhase = clusterPhase; - channelParams->m_losPhase = losPhase; - - //Step 11: Generate channel coefficients for each cluster n and each receiver and transmitter element pair u,s. - - complex3DVector_t H_NLOS; // channel coefficients H_NLOS [u][s][n], - // where u and s are receive and transmit antenna element, n is cluster index. - uint64_t uSize = rxAntennaNum[0] * rxAntennaNum[1]; - uint64_t sSize = txAntennaNum[0] * txAntennaNum[1]; - - uint8_t cluster1st = 0, cluster2nd = 0; // first and second strongest cluster; - double maxPower = 0; - for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++) - { - if (maxPower < clusterPower.at (cIndex)) - { - maxPower = clusterPower.at (cIndex); - cluster1st = cIndex; - } - } - maxPower = 0; - for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++) - { - if (maxPower < clusterPower.at (cIndex) && cluster1st != cIndex) - { - maxPower = clusterPower.at (cIndex); - cluster2nd = cIndex; - } - } - - NS_LOG_INFO ("1st strongest cluster:" << (int)cluster1st << ", 2nd strongest cluster:" << (int)cluster2nd); - - complex3DVector_t H_usn; //channel coffecient H_usn[u][s][n]; - //Since each of the strongest 2 clusters are divided into 3 sub-clusters, the total cluster will be numReducedCLuster + 4. - - H_usn.resize (uSize); - for (uint64_t uIndex = 0; uIndex < uSize; uIndex++) - { - H_usn.at (uIndex).resize (sSize); - for (uint64_t sIndex = 0; sIndex < sSize; sIndex++) - { - H_usn.at (uIndex).at (sIndex).resize (numReducedCluster); - } - } - //double slotTime = Simulator::Now ().GetSeconds (); - // The following for loops computes the channel coefficients - for (uint64_t uIndex = 0; uIndex < uSize; uIndex++) - { - Vector uLoc = rxAntenna->GetAntennaLocation (uIndex,rxAntennaNum); - - for (uint64_t sIndex = 0; sIndex < sSize; sIndex++) - { - - Vector sLoc = txAntenna->GetAntennaLocation (sIndex,txAntennaNum); - - for (uint8_t nIndex = 0; nIndex < numReducedCluster; nIndex++) - { - //Compute the N-2 weakest cluster, only vertical polarization. (7.5-22) - if (nIndex != cluster1st && nIndex != cluster2nd) - { - std::complex rays (0,0); - for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++) - { - double initialPhase = clusterPhase.at (nIndex).at (mIndex); - //lambda_0 is accounted in the antenna spacing uLoc and sLoc. - double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x - + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y - + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z); - - double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x - + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y - + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z); - //Doppler is computed in the CalBeamformingGain function and is simplified to only account for the center anngle of each cluster. - //double doppler = 2*M_PI*(sin(rayZoa_radian[nIndex][mIndex])*cos(rayAoa_radian[nIndex][mIndex])*relativeSpeed.x - // + sin(rayZoa_radian[nIndex][mIndex])*sin(rayAoa_radian[nIndex][mIndex])*relativeSpeed.y - // + cos(rayZoa_radian[nIndex][mIndex])*relativeSpeed.z)*slotTime*m_phyMacConfig->GetCenterFrequency ()/3e8; - rays += exp (std::complex (0, initialPhase)) - * (rxAntenna->GetRadiationPattern (rayZoa_radian[nIndex][mIndex],rayAoa_radian[nIndex][mIndex]) - * txAntenna->GetRadiationPattern (rayZod_radian[nIndex][mIndex],rayAod_radian[nIndex][mIndex])) - * exp (std::complex (0, rxPhaseDiff)) - * exp (std::complex (0, txPhaseDiff)); - //*exp(std::complex(0, doppler)); - //rays += 1; - } - //rays *= sqrt(clusterPower.at(nIndex))/raysPerCluster; - rays *= sqrt (clusterPower.at (nIndex) / raysPerCluster); - H_usn.at (uIndex).at (sIndex).at (nIndex) = rays; - } - else //(7.5-28) - { - std::complex raysSub1 (0,0); - std::complex raysSub2 (0,0); - std::complex raysSub3 (0,0); - - for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++) - { - - //ZML:Just remind me that the angle offsets for the 3 subclusters were not generated correctly. - - double initialPhase = clusterPhase.at (nIndex).at (mIndex); - double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x - + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y - + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z); - double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x - + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y - + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z); - //double doppler = 2*M_PI*(sin(rayZoa_radian[nIndex][mIndex])*cos(rayAoa_radian[nIndex][mIndex])*relativeSpeed.x - // + sin(rayZoa_radian[nIndex][mIndex])*sin(rayAoa_radian[nIndex][mIndex])*relativeSpeed.y - // + cos(rayZoa_radian[nIndex][mIndex])*relativeSpeed.z)*slotTime*m_phyMacConfig->GetCenterFrequency ()/3e8; - //double delaySpread; - switch (mIndex) - { - case 9: - case 10: - case 11: - case 12: - case 17: - case 18: - //delaySpread= -2*M_PI*(clusterDelay.at(nIndex)+1.28*c_DS)*m_phyMacConfig->GetCenterFrequency (); - raysSub2 += exp (std::complex (0, initialPhase)) - * (rxAntenna->GetRadiationPattern (rayZoa_radian[nIndex][mIndex],rayAoa_radian[nIndex][mIndex]) - * txAntenna->GetRadiationPattern (rayZod_radian[nIndex][mIndex],rayAod_radian[nIndex][mIndex])) - * exp (std::complex (0, rxPhaseDiff)) - * exp (std::complex (0, txPhaseDiff)); - //*exp(std::complex(0, doppler)); - //raysSub2 +=1; - break; - case 13: - case 14: - case 15: - case 16: - //delaySpread = -2*M_PI*(clusterDelay.at(nIndex)+2.56*c_DS)*m_phyMacConfig->GetCenterFrequency (); - raysSub3 += exp (std::complex (0, initialPhase)) - * (rxAntenna->GetRadiationPattern (rayZoa_radian[nIndex][mIndex],rayAoa_radian[nIndex][mIndex]) - * txAntenna->GetRadiationPattern (rayZod_radian[nIndex][mIndex],rayAod_radian[nIndex][mIndex])) - * exp (std::complex (0, rxPhaseDiff)) - * exp (std::complex (0, txPhaseDiff)); - //*exp(std::complex(0, doppler)); - //raysSub3 +=1; - break; - default: //case 1,2,3,4,5,6,7,8,19,20 - //delaySpread = -2*M_PI*clusterDelay.at(nIndex)*m_phyMacConfig->GetCenterFrequency (); - raysSub1 += exp (std::complex (0, initialPhase)) - * (rxAntenna->GetRadiationPattern (rayZoa_radian[nIndex][mIndex],rayAoa_radian[nIndex][mIndex]) - * txAntenna->GetRadiationPattern (rayZod_radian[nIndex][mIndex],rayAod_radian[nIndex][mIndex])) - * exp (std::complex (0, rxPhaseDiff)) - * exp (std::complex (0, txPhaseDiff)); - //*exp(std::complex(0, doppler)); - //raysSub1 +=1; - break; - } - } - //raysSub1 *= sqrt(clusterPower.at(nIndex))/raysPerCluster; - //raysSub2 *= sqrt(clusterPower.at(nIndex))/raysPerCluster; - //raysSub3 *= sqrt(clusterPower.at(nIndex))/raysPerCluster; - raysSub1 *= sqrt (clusterPower.at (nIndex) / raysPerCluster); - raysSub2 *= sqrt (clusterPower.at (nIndex) / raysPerCluster); - raysSub3 *= sqrt (clusterPower.at (nIndex) / raysPerCluster); - H_usn.at (uIndex).at (sIndex).at (nIndex) = raysSub1; - H_usn.at (uIndex).at (sIndex).push_back (raysSub2); - H_usn.at (uIndex).at (sIndex).push_back (raysSub3); - - } - } - if (condition == 'l') //(7.5-29) && (7.5-30) - { - std::complex ray (0,0); - double rxPhaseDiff = 2 * M_PI * (sin (rxAngle.GetInclination ()) * cos (rxAngle.GetAzimuth ()) * uLoc.x - + sin (rxAngle.GetInclination ()) * sin (rxAngle.GetAzimuth ()) * uLoc.y - + cos (rxAngle.GetInclination ()) * uLoc.z); - double txPhaseDiff = 2 * M_PI * (sin (txAngle.GetInclination ()) * cos (txAngle.GetAzimuth ()) * sLoc.x - + sin (txAngle.GetInclination ()) * sin (txAngle.GetAzimuth ()) * sLoc.y - + cos (txAngle.GetInclination ()) * sLoc.z); - //double doppler = 2*M_PI*(sin(rxAngle.GetInclination ())*cos(rxAngle.GetAzimuth ())*relativeSpeed.x - // + sin(rxAngle.GetInclination ())*sin(rxAngle.GetAzimuth ())*relativeSpeed.y - // + cos(rxAngle.GetInclination ())*relativeSpeed.z)*slotTime*m_phyMacConfig->GetCenterFrequency ()/3e8; - - ray = exp (std::complex (0, losPhase)) - * (rxAntenna->GetRadiationPattern (rxAngle.GetInclination (),rxAngle.GetAzimuth ()) - * txAntenna->GetRadiationPattern (txAngle.GetInclination (),rxAngle.GetAzimuth ())) - * exp (std::complex (0, rxPhaseDiff)) - * exp (std::complex (0, txPhaseDiff)); - //*exp(std::complex(0, doppler)); - - double K_linear = pow (10,K_factor / 10); - // the LOS path should be attenuated if blockage is enabled. - H_usn.at (uIndex).at (sIndex).at (0) = sqrt (1 / (K_linear + 1)) * H_usn.at (uIndex).at (sIndex).at (0) + sqrt (K_linear / (1 + K_linear)) * ray / pow (10,attenuation_dB.at (0) / 10); //(7.5-30) for tau = tau1 - double tempSize = H_usn.at (uIndex).at (sIndex).size (); - for (uint8_t nIndex = 1; nIndex < tempSize; nIndex++) - { - H_usn.at (uIndex).at (sIndex).at (nIndex) *= sqrt (1 / (K_linear + 1)); //(7.5-30) for tau = tau2...taunN - } - - } - } - } - - if (cluster1st == cluster2nd) - { - clusterDelay.push_back (clusterDelay.at (cluster1st) + 1.28 * table3gpp->m_cDS); - clusterDelay.push_back (clusterDelay.at (cluster1st) + 2.56 * table3gpp->m_cDS); - - clusterAoa.push_back (clusterAoa.at (cluster1st)); - clusterAoa.push_back (clusterAoa.at (cluster1st)); - - clusterZoa.push_back (clusterZoa.at (cluster1st)); - clusterZoa.push_back (clusterZoa.at (cluster1st)); - - clusterAod.push_back (clusterAod.at (cluster1st)); - clusterAod.push_back (clusterAod.at (cluster1st)); - - clusterZod.push_back (clusterZod.at (cluster1st)); - clusterZod.push_back (clusterZod.at (cluster1st)); - } - else - { - double min, max; - if (cluster1st < cluster2nd) - { - min = cluster1st; - max = cluster2nd; - } - else - { - min = cluster2nd; - max = cluster1st; - } - clusterDelay.push_back (clusterDelay.at (min) + 1.28 * table3gpp->m_cDS); - clusterDelay.push_back (clusterDelay.at (min) + 2.56 * table3gpp->m_cDS); - clusterDelay.push_back (clusterDelay.at (max) + 1.28 * table3gpp->m_cDS); - clusterDelay.push_back (clusterDelay.at (max) + 2.56 * table3gpp->m_cDS); - - clusterAoa.push_back (clusterAoa.at (min)); - clusterAoa.push_back (clusterAoa.at (min)); - clusterAoa.push_back (clusterAoa.at (max)); - clusterAoa.push_back (clusterAoa.at (max)); - - clusterZoa.push_back (clusterZoa.at (min)); - clusterZoa.push_back (clusterZoa.at (min)); - clusterZoa.push_back (clusterZoa.at (max)); - clusterZoa.push_back (clusterZoa.at (max)); - - clusterAod.push_back (clusterAod.at (min)); - clusterAod.push_back (clusterAod.at (min)); - clusterAod.push_back (clusterAod.at (max)); - clusterAod.push_back (clusterAod.at (max)); - - clusterZod.push_back (clusterZod.at (min)); - clusterZod.push_back (clusterZod.at (min)); - clusterZod.push_back (clusterZod.at (max)); - clusterZod.push_back (clusterZod.at (max)); - - - } - - NS_LOG_INFO ("size of coefficient matrix =[" << H_usn.size () << "][" << H_usn.at (0).size () << "][" << H_usn.at (0).at (0).size () << "]"); - - - /*std::cout << "Delay:"; - for (uint8_t i = 0; i < clusterDelay.size(); i++) - { - std::cout <m_channel = H_usn; - channelParams->m_delay = clusterDelay; - - channelParams->m_angle.clear (); - channelParams->m_angle.push_back (clusterAoa); - channelParams->m_angle.push_back (clusterZoa); - channelParams->m_angle.push_back (clusterAod); - channelParams->m_angle.push_back (clusterZod); - - return channelParams; - -} - -Ptr -MmWaveVehicularSpectrumPropagationLossModel::UpdateChannel (Ptr params3gpp, Ptr table3gpp, - Ptr txAntenna, Ptr rxAntenna, - uint16_t *txAntennaNum, uint16_t *rxAntennaNum, Angles &rxAngle, Angles &txAngle) const -{ - Ptr params = params3gpp; - uint8_t raysPerCluster = table3gpp->m_raysPerCluster; - //We first update the current location, the previous location will be updated in the end. - - - //Step 4: Get LSP from previous channel - double DS = params->m_DS; - double K_factor = params->m_K; - - //Step 5: Update Delays. - //copy delay from previous channel. - doubleVector_t clusterDelay; - for (uint8_t cInd = 0; cInd < params->m_numCluster; cInd++) - { - clusterDelay.push_back (params->m_delay.at (cInd)); - } - //If LOS condition, we need to revert the tau^LOS_n back to tau_n. - if (params->m_condition == 'l') - { - double C_tau = 0.7705 - 0.0433 * K_factor + 2e-4 * pow (K_factor,2) + 17e-6 * pow (K_factor,3); //(7.5-3) - for (uint8_t cIndex = 0; cIndex < params->m_numCluster; cIndex++) - { - clusterDelay.at (cIndex) = clusterDelay.at (cIndex) * C_tau; - } - } - //update delay based on equation (7.6-9) - for (uint8_t cIndex = 0; cIndex < params->m_numCluster; cIndex++) - { - clusterDelay.at (cIndex) -= (sin (params->m_angle.at (ZOA_INDEX).at (cIndex) * M_PI / 180) * cos (params->m_angle.at (AOA_INDEX).at (cIndex) * M_PI / 180) * params->m_speed.x - + sin (params->m_angle.at (ZOA_INDEX).at (cIndex) * M_PI / 180) * sin (params->m_angle.at (AOA_INDEX).at (cIndex) * M_PI / 180) * params->m_speed.y) * m_updatePeriod.GetSeconds () / 3e8; //(7.6-9) - } - - /* since the scaled Los delays are not to be used in cluster power generation, - * we will generate cluster power first and resume to compute Los cluster delay later.*/ - - //Step 6: Generate cluster powers. - doubleVector_t clusterPower; - double powerSum = 0; - for (uint8_t cIndex = 0; cIndex < params->m_numCluster; cIndex++) - { - double power = exp (-1 * clusterDelay.at (cIndex) * (table3gpp->m_rTau - 1) / table3gpp->m_rTau / DS) * - pow (10,-1 * m_normalRv->GetValue () * table3gpp->m_shadowingStd / 10); //(7.5-5) - powerSum += power; - clusterPower.push_back (power); - } - - // we do not need to compute the cluster power of LOS case, since it is used for generating angles. - for (uint8_t cIndex = 0; cIndex < params->m_numCluster; cIndex++) - { - clusterPower.at (cIndex) = clusterPower.at (cIndex) / powerSum; //(7.5-6) - } - - // Resume step 5 to compute the delay for LoS condition. - if (params->m_condition == 'l') - { - double C_tau = 0.7705 - 0.0433 * K_factor + 2e-4 * pow (K_factor,2) + 17e-6 * pow (K_factor,3); //(7.5-3) - for (uint8_t cIndex = 0; cIndex < params->m_numCluster; cIndex++) - { - clusterDelay.at (cIndex) = clusterDelay.at (cIndex) / C_tau; //(7.5-4) - } - } - - /*std::cout << "Delay:"; - for (uint8_t i = 0; i < params->m_numCluster; i++) - { - std::cout <m_numCluster; i++) - { - std::cout <m_numCluster; cIndex++) - { - clusterAoa.push_back (params->m_angle.at (AOA_INDEX).at (cIndex)); - clusterZoa.push_back (params->m_angle.at (ZOA_INDEX).at (cIndex)); - clusterAod.push_back (params->m_angle.at (AOD_INDEX).at (cIndex)); - clusterZod.push_back (params->m_angle.at (ZOD_INDEX).at (cIndex)); - } - double v = sqrt (params->m_speed.x * params->m_speed.x + params->m_speed.y * params->m_speed.y); - if (v > 1e-6) //Update the angles only when the speed is not 0. - { - if (params->m_norRvAngles.size () == 0) - { - //initial case - for (uint8_t cInd = 0; cInd < params->m_numCluster; cInd++) - { - doubleVector_t temp; - temp.push_back (0); //initial random angle for AOA - temp.push_back (0); //initial random angle for ZOA - temp.push_back (0); //initial random angle for AOD - temp.push_back (0); //initial random angle for ZOD - params->m_norRvAngles.push_back (temp); - } - } - for (uint8_t cInd = 0; cInd < params->m_numCluster; cInd++) - { - double timeDiff = Now ().GetSeconds () - params->m_generatedTime.GetSeconds (); - double ranPhiAOD, ranThetaZOD, ranPhiAOA, ranThetaZOA; - if (params->m_condition == 'l' && cInd == 0) //These angles equal 0 for LOS path. - { - ranPhiAOD = 0; - ranThetaZOD = 0; - ranPhiAOA = 0; - ranThetaZOA = 0; - } - else - { - double deltaX = sqrt (pow (params->m_preLocUT.x - params->m_locUT.x, 2) + pow (params->m_preLocUT.y - params->m_locUT.y, 2)); - double R_phi = exp (-1 * deltaX / 50); // 50 m is the correlation distance as specified in TR 38.900 Sec 7.6.3.2 - double R_theta = exp (-1 * deltaX / 100); // 100 m is the correlation distance as specified in TR 38.900 Sec 7.6.3.2 - - //In order to generate correlated uniform random variables, we first generate correlated normal random variables and map the normal RV to uniform RV. - //Notice the correlation will change if the RV is transformed from normal to uniform. - //To compensate the distortion, the correlation of the normal RV is computed - //such that the uniform RV would have the desired correlation when transformed from normal RV. - - //The following formula was obtained from MATLAB numerical simulation. - - if (R_phi * R_phi * (-0.069) + R_phi * 1.074 - 0.002 < 1) //When the correlation for normal RV is close to 1, no need to transform. - { - R_phi = R_phi * R_phi * (-0.069) + R_phi * 1.074 - 0.002; - } - if (R_theta * R_theta * (-0.069) + R_theta * 1.074 - 0.002 < 1) - { - R_theta = R_theta * R_theta * (-0.069) + R_theta * 1.074 - 0.002; - } - - //We can generate a new correlated normal RV with the following formula - params->m_norRvAngles.at (cInd).at (AOD_INDEX) = R_phi * params->m_norRvAngles.at (cInd).at (AOD_INDEX) + sqrt (1 - R_phi * R_phi) * m_normalRv->GetValue (); - params->m_norRvAngles.at (cInd).at (ZOD_INDEX) = R_theta * params->m_norRvAngles.at (cInd).at (ZOD_INDEX) + sqrt (1 - R_theta * R_theta) * m_normalRv->GetValue (); - params->m_norRvAngles.at (cInd).at (AOA_INDEX) = R_phi * params->m_norRvAngles.at (cInd).at (AOA_INDEX) + sqrt (1 - R_phi * R_phi) * m_normalRv->GetValue (); - params->m_norRvAngles.at (cInd).at (ZOA_INDEX) = R_theta * params->m_norRvAngles.at (cInd).at (ZOA_INDEX) + sqrt (1 - R_theta * R_theta) * m_normalRv->GetValue (); - - //The normal RV is transformed to uniform RV with the desired correlation. - ranPhiAOD = (0.5 * erfc (-1 * params->m_norRvAngles.at (cInd).at (AOD_INDEX) / sqrt (2))) * 2 * M_PI - M_PI; - ranThetaZOD = (0.5 * erfc (-1 * params->m_norRvAngles.at (cInd).at (ZOD_INDEX) / sqrt (2))) * M_PI - 0.5 * M_PI; - ranPhiAOA = (0.5 * erfc (-1 * params->m_norRvAngles.at (cInd).at (AOA_INDEX) / sqrt (2))) * 2 * M_PI - M_PI; - ranThetaZOA = (0.5 * erfc (-1 * params->m_norRvAngles.at (cInd).at (ZOA_INDEX) / sqrt (2))) * M_PI - 0.5 * M_PI; - } - clusterAod.at (cInd) += v * timeDiff * - sin (atan (params->m_speed.y / params->m_speed.x) - clusterAod.at (cInd) * M_PI / 180 + ranPhiAOD) * 180 / (M_PI * params->m_dis2D); - clusterZod.at (cInd) -= v * timeDiff * - cos (atan (params->m_speed.y / params->m_speed.x) - clusterAod.at (cInd) * M_PI / 180 + ranThetaZOD) * 180 / (M_PI * params->m_dis3D); - clusterAoa.at (cInd) -= v * timeDiff * - sin (atan (params->m_speed.y / params->m_speed.x) - clusterAoa.at (cInd) * M_PI / 180 + ranPhiAOA) * 180 / (M_PI * params->m_dis2D); - clusterZoa.at (cInd) -= v * timeDiff * - cos (atan (params->m_speed.y / params->m_speed.x) - clusterAoa.at (cInd) * M_PI / 180 + ranThetaZOA) * 180 / (M_PI * params->m_dis3D); - } - } - - - double rayAoa_radian[params->m_numCluster][raysPerCluster]; //rayAoa_radian[n][m], where n is cluster index, m is ray index - double rayAod_radian[params->m_numCluster][raysPerCluster]; //rayAod_radian[n][m], where n is cluster index, m is ray index - double rayZoa_radian[params->m_numCluster][raysPerCluster]; //rayZoa_radian[n][m], where n is cluster index, m is ray index - double rayZod_radian[params->m_numCluster][raysPerCluster]; //rayZod_radian[n][m], where n is cluster index, m is ray index - - for (uint8_t nInd = 0; nInd < params->m_numCluster; nInd++) - { - for (uint8_t mInd = 0; mInd < raysPerCluster; mInd++) - { - double tempAoa = clusterAoa.at (nInd) + table3gpp->m_cASA * offSetAlpha[mInd]; //(7.5-13) - while (tempAoa > 360) - { - tempAoa -= 360; - } - - while (tempAoa < 0) - { - tempAoa += 360; - - } - NS_ASSERT_MSG (tempAoa >= 0 && tempAoa <= 360, "the AOA should be the range of [0,360]"); - rayAoa_radian[nInd][mInd] = tempAoa * M_PI / 180; - - double tempAod = clusterAod.at (nInd) + table3gpp->m_cASD * offSetAlpha[mInd]; - while (tempAod > 360) - { - tempAod -= 360; - } - - while (tempAod < 0) - { - tempAod += 360; - } - NS_ASSERT_MSG (tempAod >= 0 && tempAod <= 360, "the AOD should be the range of [0,360]"); - rayAod_radian[nInd][mInd] = tempAod * M_PI / 180; - - double tempZoa = clusterZoa.at (nInd) + table3gpp->m_cZSA * offSetAlpha[mInd]; //(7.5-18) - - while (tempZoa > 360) - { - tempZoa -= 360; - } - - while (tempZoa < 0) - { - tempZoa += 360; - } - - if (tempZoa > 180) - { - tempZoa = 360 - tempZoa; - } - - NS_ASSERT_MSG (tempZoa >= 0&&tempZoa <= 180, "the ZOA should be the range of [0,180]"); - rayZoa_radian[nInd][mInd] = tempZoa * M_PI / 180; - - double tempZod = clusterZod.at (nInd) + 0.375 * pow (10,table3gpp->m_uLgZSD) * offSetAlpha[mInd]; //(7.5-20) - - while (tempZod > 360) - { - tempZod -= 360; - } - - while (tempZod < 0) - { - tempZod += 360; - } - if (tempZod > 180) - { - tempZod = 360 - tempZod; - } - NS_ASSERT_MSG (tempZod >= 0&&tempZod <= 180, "the ZOD should be the range of [0,180]"); - rayZod_radian[nInd][mInd] = tempZod * M_PI / 180; - } - } - - doubleVector_t angle_degree; - double sizeTemp = clusterZoa.size (); - for (uint8_t ind = 0; ind < 4; ind++) - { - switch (ind) - { - case 0: - angle_degree = clusterAoa; - break; - case 1: - angle_degree = clusterZoa; - break; - case 2: - angle_degree = clusterAod; - break; - case 3: - angle_degree = clusterZod; - break; - default: - NS_FATAL_ERROR ("Programming Error"); - } - - for (uint8_t nIndex = 0; nIndex < sizeTemp; nIndex++) - { - while (angle_degree[nIndex] > 360) - { - angle_degree[nIndex] -= 360; - } - - while (angle_degree[nIndex] < 0) - { - angle_degree[nIndex] += 360; - } - - if (ind == 1 || ind == 3) - { - if (angle_degree[nIndex] > 180) - { - angle_degree[nIndex] = 360 - angle_degree[nIndex]; - } - } - } - switch (ind) - { - case 0: - clusterAoa = angle_degree; - break; - case 1: - clusterZoa = angle_degree; - break; - case 2: - clusterAod = angle_degree; - break; - case 3: - clusterZod = angle_degree; - break; - default: - NS_FATAL_ERROR ("Programming Error"); - } - } - doubleVector_t attenuation_dB; - if (m_blockage) - { - attenuation_dB = CalAttenuationOfBlockage (params, clusterAoa, clusterZoa); - for (uint8_t cInd = 0; cInd < params->m_numCluster; cInd++) - { - clusterPower.at (cInd) = clusterPower.at (cInd) / pow (10,attenuation_dB.at (cInd) / 10); - } - } - else - { - attenuation_dB.push_back (0); - } - - /*std::cout << "BlockedPower:"; - for (uint8_t i = 0; i < params->m_numCluster; i++) - { - std::cout <m_numCluster; i++) - { - std::cout <m_numCluster; i++) - { - std::cout <m_numCluster; i++) - { - std::cout <m_numCluster; i++) - { - std::cout <m_numCluster; cIndex++) - { - std::shuffle (&rayAod_radian[cIndex][0],&rayAod_radian[cIndex][raysPerCluster],std::default_random_engine (cIndex * 1000 + 100)); - std::shuffle (&rayAoa_radian[cIndex][0],&rayAoa_radian[cIndex][raysPerCluster],std::default_random_engine (cIndex * 1000 + 200)); - std::shuffle (&rayZod_radian[cIndex][0],&rayZod_radian[cIndex][raysPerCluster],std::default_random_engine (cIndex * 1000 + 300)); - std::shuffle (&rayZoa_radian[cIndex][0],&rayZoa_radian[cIndex][raysPerCluster],std::default_random_engine (cIndex * 1000 + 400)); - } - - //Step 9: Generate the cross polarization power ratios - //This step is skipped, only vertical polarization is considered in this version - - //Step 10: Draw initial phases - double2DVector_t clusterPhase = params->m_clusterPhase; //rayAoa_radian[n][m], where n is cluster index, m is ray index - double losPhase = params->m_losPhase; - // these two should also be generated from previous channel. - - //Step 11: Generate channel coefficients for each cluster n and each receiver and transmitter element pair u,s. - - complex3DVector_t H_NLOS; // channel coefficients H_NLOS [u][s][n], - // where u and s are receive and transmit antenna element, n is cluster index. - uint64_t uSize = rxAntennaNum[0] * rxAntennaNum[1]; - uint64_t sSize = txAntennaNum[0] * txAntennaNum[1]; - - uint8_t cluster1st = 0, cluster2nd = 0; // first and second strongest cluster; - double maxPower = 0; - for (uint8_t cIndex = 0; cIndex < params->m_numCluster; cIndex++) - { - if (maxPower < clusterPower.at (cIndex)) - { - maxPower = clusterPower.at (cIndex); - cluster1st = cIndex; - } - } - maxPower = 0; - for (uint8_t cIndex = 0; cIndex < params->m_numCluster; cIndex++) - { - if (maxPower < clusterPower.at (cIndex) && cluster1st != cIndex) - { - maxPower = clusterPower.at (cIndex); - cluster2nd = cIndex; - } - } - - NS_LOG_INFO ("1st strongest cluster:" << (int)cluster1st << ", 2nd strongest cluster:" << (int)cluster2nd); - - complex3DVector_t H_usn; //channel coffecient H_usn[u][s][n]; - //Since each of the strongest 2 clusters are divided into 3 sub-clusters, the total cluster will be numReducedCLuster + 4. - - H_usn.resize (uSize); - for (uint64_t uIndex = 0; uIndex < uSize; uIndex++) - { - H_usn.at (uIndex).resize (sSize); - for (uint64_t sIndex = 0; sIndex < sSize; sIndex++) - { - H_usn.at (uIndex).at (sIndex).resize (params->m_numCluster); - } - } - //double slotTime = Simulator::Now ().GetSeconds (); - // The following for loops computes the channel coefficients - for (uint64_t uIndex = 0; uIndex < uSize; uIndex++) - { - Vector uLoc = rxAntenna->GetAntennaLocation (uIndex,rxAntennaNum); - - for (uint64_t sIndex = 0; sIndex < sSize; sIndex++) - { - - Vector sLoc = txAntenna->GetAntennaLocation (sIndex,txAntennaNum); - - for (uint8_t nIndex = 0; nIndex < params->m_numCluster; nIndex++) - { - //Compute the N-2 weakest cluster, only vertical polarization. (7.5-22) - if (nIndex != cluster1st && nIndex != cluster2nd) - { - std::complex rays (0,0); - for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++) - { - double initialPhase = clusterPhase.at (nIndex).at (mIndex); - //lambda_0 is accounted in the antenna spacing uLoc and sLoc. - double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x - + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y - + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z); - - double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x - + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y - + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z); - //Doppler is computed in the CalBeamformingGain function and is simplified to only account for the center anngle of each cluster. - //double doppler = 2*M_PI*(sin(rayZoa_radian[nIndex][mIndex])*cos(rayAoa_radian[nIndex][mIndex])*relativeSpeed.x - // + sin(rayZoa_radian[nIndex][mIndex])*sin(rayAoa_radian[nIndex][mIndex])*relativeSpeed.y - // + cos(rayZoa_radian[nIndex][mIndex])*relativeSpeed.z)*slotTime*m_phyMacConfig->GetCenterFrequency ()/3e8; - rays += exp (std::complex (0, initialPhase)) - * (rxAntenna->GetRadiationPattern (rayZoa_radian[nIndex][mIndex],rayAoa_radian[nIndex][mIndex]) - * txAntenna->GetRadiationPattern (rayZod_radian[nIndex][mIndex],rayAod_radian[nIndex][mIndex])) - * exp (std::complex (0, rxPhaseDiff)) - * exp (std::complex (0, txPhaseDiff)); - //*exp(std::complex(0, doppler)); - //rays += 1; - } - //rays *= sqrt(clusterPower.at(nIndex))/raysPerCluster; - rays *= sqrt (clusterPower.at (nIndex) / raysPerCluster); - H_usn.at (uIndex).at (sIndex).at (nIndex) = rays; - } - else //(7.5-28) - { - std::complex raysSub1 (0,0); - std::complex raysSub2 (0,0); - std::complex raysSub3 (0,0); - - for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++) - { - double initialPhase = clusterPhase.at (nIndex).at (mIndex); - double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x - + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y - + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z); - double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x - + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y - + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z); - //double doppler = 2*M_PI*(sin(rayZoa_radian[nIndex][mIndex])*cos(rayAoa_radian[nIndex][mIndex])*relativeSpeed.x - // + sin(rayZoa_radian[nIndex][mIndex])*sin(rayAoa_radian[nIndex][mIndex])*relativeSpeed.y - // + cos(rayZoa_radian[nIndex][mIndex])*relativeSpeed.z)*slotTime*m_phyMacConfig->GetCenterFrequency ()/3e8; - //double delaySpread; - switch (mIndex) - { - case 9: - case 10: - case 11: - case 12: - case 17: - case 18: - //delaySpread= -2*M_PI*(clusterDelay.at(nIndex)+1.28*c_DS)*m_phyMacConfig->GetCenterFrequency (); - raysSub2 += exp (std::complex (0, initialPhase)) - * (rxAntenna->GetRadiationPattern (rayZoa_radian[nIndex][mIndex],rayAoa_radian[nIndex][mIndex]) - * txAntenna->GetRadiationPattern (rayZod_radian[nIndex][mIndex],rayAod_radian[nIndex][mIndex])) - * exp (std::complex (0, rxPhaseDiff)) - * exp (std::complex (0, txPhaseDiff)); - //*exp(std::complex(0, doppler)); - //raysSub2 +=1; - break; - case 13: - case 14: - case 15: - case 16: - //delaySpread = -2*M_PI*(clusterDelay.at(nIndex)+2.56*c_DS)*m_phyMacConfig->GetCenterFrequency (); - raysSub3 += exp (std::complex (0, initialPhase)) - * (rxAntenna->GetRadiationPattern (rayZoa_radian[nIndex][mIndex],rayAoa_radian[nIndex][mIndex]) - * txAntenna->GetRadiationPattern (rayZod_radian[nIndex][mIndex],rayAod_radian[nIndex][mIndex])) - * exp (std::complex (0, rxPhaseDiff)) - * exp (std::complex (0, txPhaseDiff)); - //*exp(std::complex(0, doppler)); - //raysSub3 +=1; - break; - default: //case 1,2,3,4,5,6,7,8,19,20 - //delaySpread = -2*M_PI*clusterDelay.at(nIndex)*m_phyMacConfig->GetCenterFrequency (); - raysSub1 += exp (std::complex (0, initialPhase)) - * (rxAntenna->GetRadiationPattern (rayZoa_radian[nIndex][mIndex],rayAoa_radian[nIndex][mIndex]) - * txAntenna->GetRadiationPattern (rayZod_radian[nIndex][mIndex],rayAod_radian[nIndex][mIndex])) - * exp (std::complex (0, rxPhaseDiff)) - * exp (std::complex (0, txPhaseDiff)); - //*exp(std::complex(0, doppler)); - //raysSub1 +=1; - break; - } - } - //raysSub1 *= sqrt(clusterPower.at(nIndex))/raysPerCluster; - //raysSub2 *= sqrt(clusterPower.at(nIndex))/raysPerCluster; - //raysSub3 *= sqrt(clusterPower.at(nIndex))/raysPerCluster; - raysSub1 *= sqrt (clusterPower.at (nIndex) / raysPerCluster); - raysSub2 *= sqrt (clusterPower.at (nIndex) / raysPerCluster); - raysSub3 *= sqrt (clusterPower.at (nIndex) / raysPerCluster); - H_usn.at (uIndex).at (sIndex).at (nIndex) = raysSub1; - H_usn.at (uIndex).at (sIndex).push_back (raysSub2); - H_usn.at (uIndex).at (sIndex).push_back (raysSub3); - - } - } - if (params->m_condition == 'l') //(7.5-29) && (7.5-30) - { - std::complex ray (0,0); - double rxPhaseDiff = 2 * M_PI * (sin (rxAngle.GetInclination ()) * cos (rxAngle.GetAzimuth ()) * uLoc.x - + sin (rxAngle.GetInclination ()) * sin (rxAngle.GetAzimuth ()) * uLoc.y - + cos (rxAngle.GetInclination ()) * uLoc.z); - double txPhaseDiff = 2 * M_PI * (sin (txAngle.GetInclination ()) * cos (txAngle.GetAzimuth ()) * sLoc.x - + sin (txAngle.GetInclination ()) * sin (txAngle.GetAzimuth ()) * sLoc.y - + cos (txAngle.GetInclination ()) * sLoc.z); - //double doppler = 2*M_PI*(sin(rxAngle.GetInclination ())*cos(rxAngle.GetAzimuth ())*relativeSpeed.x - // + sin(rxAngle.GetInclination ())*sin(rxAngle.GetAzimuth ())*relativeSpeed.y - // + cos(rxAngle.GetInclination ())*relativeSpeed.z)*slotTime*m_phyMacConfig->GetCenterFrequency ()/3e8; - - ray = exp (std::complex (0, losPhase)) - * (rxAntenna->GetRadiationPattern (rxAngle.GetInclination (),rxAngle.GetAzimuth ()) - * txAntenna->GetRadiationPattern (txAngle.GetInclination (),txAngle.GetAzimuth ())) - * exp (std::complex (0, rxPhaseDiff)) - * exp (std::complex (0, txPhaseDiff)); - //*exp(std::complex(0, doppler)); - - double K_linear = pow (10,K_factor / 10); - - H_usn.at (uIndex).at (sIndex).at (0) = sqrt (1 / (K_linear + 1)) * H_usn.at (uIndex).at (sIndex).at (0) + sqrt (K_linear / (1 + K_linear)) * ray / pow (10,attenuation_dB.at (0) / 10); //(7.5-30) for tau = tau1 - double tempSize = H_usn.at (uIndex).at (sIndex).size (); - for (uint8_t nIndex = 1; nIndex < tempSize; nIndex++) - { - H_usn.at (uIndex).at (sIndex).at (nIndex) *= sqrt (1 / (K_linear + 1)); //(7.5-30) for tau = tau2...taunN - } - - } - } - } - - if (cluster1st == cluster2nd) - { - clusterDelay.push_back (clusterDelay.at (cluster2nd) + 1.28 * table3gpp->m_cDS); - clusterDelay.push_back (clusterDelay.at (cluster2nd) + 2.56 * table3gpp->m_cDS); - - clusterAoa.push_back (clusterAoa.at (cluster2nd)); - clusterAoa.push_back (clusterAoa.at (cluster2nd)); - clusterZoa.push_back (clusterZoa.at (cluster2nd)); - clusterZoa.push_back (clusterZoa.at (cluster2nd)); - } - else - { - double min, max; - if (cluster1st < cluster2nd) - { - min = cluster1st; - max = cluster2nd; - } - else - { - min = cluster2nd; - max = cluster1st; - } - clusterDelay.push_back (clusterDelay.at (min) + 1.28 * table3gpp->m_cDS); - clusterDelay.push_back (clusterDelay.at (min) + 2.56 * table3gpp->m_cDS); - clusterDelay.push_back (clusterDelay.at (max) + 1.28 * table3gpp->m_cDS); - clusterDelay.push_back (clusterDelay.at (max) + 2.56 * table3gpp->m_cDS); - - clusterAoa.push_back (clusterAoa.at (min)); - clusterAoa.push_back (clusterAoa.at (min)); - clusterAoa.push_back (clusterAoa.at (max)); - clusterAoa.push_back (clusterAoa.at (max)); - - clusterZoa.push_back (clusterZoa.at (min)); - clusterZoa.push_back (clusterZoa.at (min)); - clusterZoa.push_back (clusterZoa.at (max)); - clusterZoa.push_back (clusterZoa.at (max)); - - - } - - NS_LOG_INFO ("size of coefficient matrix =[" << H_usn.size () << "][" << H_usn.at (0).size () << "][" << H_usn.at (0).at (0).size () << "]"); - - - /*std::cout << "Delay:"; - for (uint8_t i = 0; i < clusterDelay.size(); i++) - { - std::cout <m_delay = clusterDelay; - params->m_channel = H_usn; - params->m_angle.clear (); - params->m_angle.push_back (clusterAoa); - params->m_angle.push_back (clusterZoa); - params->m_angle.push_back (clusterAod); - params->m_angle.push_back (clusterZod); - //update the previous location. - - return params; - -} - -doubleVector_t -MmWaveVehicularSpectrumPropagationLossModel::CalAttenuationOfBlockage (Ptr params, - doubleVector_t clusterAOA, doubleVector_t clusterZOA) const -{ - doubleVector_t powerAttenuation; - uint8_t clusterNum = clusterAOA.size (); - for (uint8_t cInd = 0; cInd < clusterNum; cInd++) - { - powerAttenuation.push_back (0); //Initial power attenuation for all clusters to be 0 dB; - } - //step a: the number of non-self blocking blockers is stored in m_numNonSelfBloking. - - //step b:Generate the size and location of each blocker - //generate self blocking (i.e., for blockage from the human body) - double phi_sb, x_sb, theta_sb, y_sb; - //table 7.6.4.1-1 Self-blocking region parameters. - if (m_portraitMode) - { - phi_sb = 260; - x_sb = 120; - theta_sb = 100; - y_sb = 80; - } - else // landscape mode - { - phi_sb = 40; - x_sb = 160; - theta_sb = 110; - y_sb = 75; - } - - //generate or update non-self blocking - if (params->m_nonSelfBlocking.size () == 0) //generate new blocking regions - { - for (uint16_t blockInd = 0; blockInd < m_numNonSelfBloking; blockInd++) - { - //draw value from table 7.6.4.1-2 Blocking region parameters - doubleVector_t table; - table.push_back (m_normalRvBlockage->GetValue ()); //phi_k: store the normal RV that will be mapped to uniform (0,360) later. - if (m_scenario == "InH-OfficeMixed" || m_scenario == "InH-OfficeOpen") - { - table.push_back (m_uniformRvBlockage->GetValue (15, 45)); //x_k - table.push_back (90); //Theta_k - table.push_back (m_uniformRvBlockage->GetValue (5, 15)); //y_k - table.push_back (2); //r - } - else - { - table.push_back (m_uniformRvBlockage->GetValue (5, 15)); //x_k - table.push_back (90); //Theta_k - table.push_back (5); //y_k - table.push_back (10); //r - } - params->m_nonSelfBlocking.push_back (table); - } - } - else - { - double deltaX = sqrt (pow (params->m_preLocUT.x - params->m_locUT.x, 2) + pow (params->m_preLocUT.y - params->m_locUT.y, 2)); - //if deltaX and speed are both 0, the autocorrelation is 1, skip updating - if (deltaX > 1e-6 || m_blockerSpeed > 1e-6) - { - double corrDis; - //draw value from table 7.6.4.1-4: Spatial correlation distance for different scenarios. - if (m_scenario == "InH-OfficeMixed" || m_scenario == "InH-OfficeOpen") - { - //InH, correlation distance = 5; - corrDis = 5; - } - else - { - if (params->m_o2i) // outdoor to indoor - { - corrDis = 5; - } - else //LOS or NLOS - { - corrDis = 10; - } - } - double R; - if (m_blockerSpeed > 1e-6) // speed not equal to 0 - { - double corrT = corrDis / m_blockerSpeed; - R = exp (-1 * (deltaX / corrDis + (Now ().GetSeconds () - params->m_generatedTime.GetSeconds ()) / corrT)); - } - else - { - R = exp (-1 * (deltaX / corrDis)); - } - - NS_LOG_INFO ("Distance change:" << deltaX << " Speed:" << m_blockerSpeed - << " Time difference:" << Now ().GetSeconds () - params->m_generatedTime.GetSeconds () - << " correlation:" << R); - - //In order to generate correlated uniform random variables, we first generate correlated normal random variables and map the normal RV to uniform RV. - //Notice the correlation will change if the RV is transformed from normal to uniform. - //To compensate the distortion, the correlation of the normal RV is computed - //such that the uniform RV would have the desired correlation when transformed from normal RV. - - //The following formula was obtained from MATLAB numerical simulation. - - if (R * R * (-0.069) + R * 1.074 - 0.002 < 1) //transform only when the correlation of normal RV is smaller than 1 - { - R = R * R * (-0.069) + R * 1.074 - 0.002; - } - for (uint16_t blockInd = 0; blockInd < m_numNonSelfBloking; blockInd++) - { - - //Generate a new correlated normal RV with the following formula - params->m_nonSelfBlocking.at (blockInd).at (PHI_INDEX) = - R * params->m_nonSelfBlocking.at (blockInd).at (PHI_INDEX) + sqrt (1 - R * R) * m_normalRvBlockage->GetValue (); - } - } - - } - - //step c: Determine the attenuation of each blocker due to blockers - for (uint8_t cInd = 0; cInd < clusterNum; cInd++) - { - NS_ASSERT_MSG (clusterAOA.at (cInd) >= 0 && clusterAOA.at (cInd) <= 360, "the AOA should be the range of [0,360]"); - NS_ASSERT_MSG (clusterZOA.at (cInd) >= 0 && clusterZOA.at (cInd) <= 180, "the ZOA should be the range of [0,180]"); - - //check self blocking - NS_LOG_INFO ("AOA=" << clusterAOA.at (cInd) << " Block Region[" << phi_sb - x_sb / 2 << "," << phi_sb + x_sb / 2 << "]"); - NS_LOG_INFO ("ZOA=" << clusterZOA.at (cInd) << " Block Region[" << theta_sb - y_sb / 2 << "," << theta_sb + y_sb / 2 << "]"); - if ( std::abs (clusterAOA.at (cInd) - phi_sb) < (x_sb / 2) && std::abs (clusterZOA.at (cInd) - theta_sb) < (y_sb / 2)) - { - powerAttenuation.at (cInd) += 30; //anttenuate by 30 dB. - NS_LOG_INFO ("Cluster[" << (int)cInd << "] is blocked by self blocking region and reduce 30 dB power," - "the attenuation is [" << powerAttenuation.at (cInd) << " dB]"); - } - - //check non-self blocking - double phiK, xK, thetaK, yK; - for (uint16_t blockInd = 0; blockInd < m_numNonSelfBloking; blockInd++) - { - //The normal RV is transformed to uniform RV with the desired correlation. - phiK = (0.5 * erfc (-1 * params->m_nonSelfBlocking.at (blockInd).at (PHI_INDEX) / sqrt (2))) * 360; - while (phiK > 360) - { - phiK -= 360; - } - - while (phiK < 0) - { - phiK += 360; - } - - xK = params->m_nonSelfBlocking.at (blockInd).at (X_INDEX); - thetaK = params->m_nonSelfBlocking.at (blockInd).at (THETA_INDEX); - yK = params->m_nonSelfBlocking.at (blockInd).at (Y_INDEX); - NS_LOG_INFO ("AOA=" << clusterAOA.at (cInd) << " Block Region[" << phiK - xK << "," << phiK + xK << "]"); - NS_LOG_INFO ("ZOA=" << clusterZOA.at (cInd) << " Block Region[" << thetaK - yK << "," << thetaK + yK << "]"); - - if ( std::abs (clusterAOA.at (cInd) - phiK) < (xK) - && std::abs (clusterZOA.at (cInd) - thetaK) < (yK)) - { - double A1 = clusterAOA.at (cInd) - (phiK + xK / 2); //(7.6-24) - double A2 = clusterAOA.at (cInd) - (phiK - xK / 2); //(7.6-25) - double Z1 = clusterZOA.at (cInd) - (thetaK + yK / 2); //(7.6-26) - double Z2 = clusterZOA.at (cInd) - (thetaK - yK / 2); //(7.6-27) - int signA1, signA2, signZ1, signZ2; - //draw sign for the above parameters according to table 7.6.4.1-3 Description of signs - if (xK / 2 < clusterAOA.at (cInd) - phiK && clusterAOA.at (cInd) - phiK <= xK) - { - signA1 = -1; - } - else - { - signA1 = 1; - } - if (-1 * xK < clusterAOA.at (cInd) - phiK && clusterAOA.at (cInd) - phiK <= -1 * xK / 2) - { - signA2 = -1; - } - else - { - signA2 = 1; - } - - if (yK / 2 < clusterZOA.at (cInd) - thetaK && clusterZOA.at (cInd) - thetaK <= yK) - { - signZ1 = -1; - } - else - { - signZ1 = 1; - } - if (-1 * yK < clusterZOA.at (cInd) - thetaK && clusterZOA.at (cInd) - thetaK <= -1 * yK / 2) - { - signZ2 = -1; - } - else - { - signZ2 = 1; - } - double lambda = 3e8 / m_frequency; - double F_A1 = atan (signA1 * M_PI / 2 * sqrt (M_PI / lambda * - params->m_nonSelfBlocking.at (blockInd).at (R_INDEX) * (1 / cos (A1 * M_PI / 180) - 1))) / M_PI; //(7.6-23) - double F_A2 = atan (signA2 * M_PI / 2 * sqrt (M_PI / lambda * - params->m_nonSelfBlocking.at (blockInd).at (R_INDEX) * (1 / cos (A2 * M_PI / 180) - 1))) / M_PI; - double F_Z1 = atan (signZ1 * M_PI / 2 * sqrt (M_PI / lambda * - params->m_nonSelfBlocking.at (blockInd).at (R_INDEX) * (1 / cos (Z1 * M_PI / 180) - 1))) / M_PI; - double F_Z2 = atan (signZ2 * M_PI / 2 * sqrt (M_PI / lambda * - params->m_nonSelfBlocking.at (blockInd).at (R_INDEX) * (1 / cos (Z2 * M_PI / 180) - 1))) / M_PI; - double L_dB = -20 * log10 (1 - (F_A1 + F_A2) * (F_Z1 + F_Z2)); //(7.6-22) - powerAttenuation.at (cInd) += L_dB; - NS_LOG_INFO ("Cluster[" << (int)cInd << "] is blocked by no-self blocking, " - "the loss is [" << L_dB << "]" << " dB"); - - } - } - } - return powerAttenuation; -} - -void -MmWaveVehicularSpectrumPropagationLossModel::SetFrequency (double freq) -{ - m_frequency = freq; -} - -double -MmWaveVehicularSpectrumPropagationLossModel::GetFrequency (void) const -{ - return m_frequency; -} - -} // namespace millicar - -} // namespace ns3 diff --git a/model/mmwave-vehicular-spectrum-propagation-loss-model.h b/model/mmwave-vehicular-spectrum-propagation-loss-model.h deleted file mode 100644 index 2db3f37..0000000 --- a/model/mmwave-vehicular-spectrum-propagation-loss-model.h +++ /dev/null @@ -1,365 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* -* Copyright (c) 2015, NYU WIRELESS, Tandon School of Engineering, New York -* University -* Copyright (c) 2016, 2018, 2020 University of Padova, Dep. of Information -* Engineering, SIGNET lab. -* -* 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 -* -*/ - - -#ifndef MMWAVE_VEHICULAR_SPECTRUM_PROPAGATION_LOSS_MODEL_H_ -#define MMWAVE_VEHICULAR_SPECTRUM_PROPAGATION_LOSS_MODEL_H_ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -// #include - -#define AOA_INDEX 0 -#define ZOA_INDEX 1 -#define AOD_INDEX 2 -#define ZOD_INDEX 3 - -#define PHI_INDEX 0 -#define X_INDEX 1 -#define THETA_INDEX 2 -#define Y_INDEX 3 -#define R_INDEX 4 - -namespace ns3 { - -namespace millicar { - -//class MmWave3gppBuildingsPropagationLossModel; - -typedef std::vector doubleVector_t; -typedef std::vector double2DVector_t; - -typedef std::vector< std::complex > complexVector_t; -typedef std::vector complex2DVector_t; -typedef std::vector complex3DVector_t; - -typedef std::pair, Ptr > key_t; - -/** - * Data structure that stores a channel realization - */ -struct Params3gpp : public SimpleRefCount -{ - complexVector_t m_txW; // tx antenna weights. - complexVector_t m_rxW; // rx antenna weights. - complex3DVector_t m_channel; // channel matrix H[u][s][n]. - doubleVector_t m_delay; // cluster delay. - double m_tauDelta; // minimum delay as indicated in 7.6-1 TR 38.901. - double2DVector_t m_angle; // cluster angle angle[direction][n], where direction = 0(aoa), 1(zoa), 2(aod), 3(zod) in degree. - complexVector_t m_longTerm; // long term component. - - double2DVector_t m_nonSelfBlocking; // store the blockages - - /*The following parameters are stored for spatial consistent updating*/ - Vector m_preLocUT; // location of UT when generating the previous channel - Vector m_locUT; // location of UT - double2DVector_t m_norRvAngles; //stores the normal variable for random angles angle[cluster][id] generated for equation (7.6-11)-(7.6-14), where id = 0(aoa),1(zoa),2(aod),3(zod) - Time m_generatedTime; - double m_DS; // delay spread - double m_K; //K factor - uint8_t m_numCluster; // reduced cluster number; - double2DVector_t m_clusterPhase; - double m_losPhase; - char m_condition; - bool m_o2i; - Vector m_speed; - double m_dis2D; - double m_dis3D; - - std::map, complexVector_t> m_allLongTermMap; -}; - -/** - * Data structure that stores the parameters of 3GPP TR 38.900, Table 7.5-6, for a certain scenario - */ -struct ParamsTable : public Object -{ - uint8_t m_numOfCluster = 0; - uint8_t m_raysPerCluster = 0; - double m_uLgDS = 0; - double m_sigLgDS = 0; - double m_uLgASD = 0; - double m_sigLgASD = 0; - double m_uLgASA = 0; - double m_sigLgASA = 0; - double m_uLgZSA = 0; - double m_sigLgZSA = 0; - double m_uLgZSD = 0; - double m_sigLgZSD = 0; - double m_offsetZOD = 0; - double m_cDS = 0; - double m_cASD = 0; - double m_cASA = 0; - double m_cZSA = 0; - double m_uK = 0; - double m_sigK = 0; - double m_rTau = 0; - double m_shadowingStd = 0; - - double m_sqrtC[7][7]; - - ParamsTable () - { - } - void SetParams (uint8_t numOfCluster, uint8_t raysPerCluster, double uLgDS, double sigLgDS, - double uLgASD, double sigLgASD, double uLgASA, double sigLgASA, - double uLgZSA, double sigLgZSA, double uLgZSD, double sigLgZSD, double offsetZOD, - double cDS, double cASD, double cASA, double cZSA, - double uK, double sigK, double rTau, double shadowingStd) - { - m_numOfCluster = numOfCluster; - m_raysPerCluster = raysPerCluster; - m_uLgDS = uLgDS; - m_sigLgDS = sigLgDS; - m_uLgASD = uLgASD; - m_sigLgASD = sigLgASD; - m_uLgASA = uLgASA; - m_sigLgASA = sigLgASA; - m_uLgZSA = uLgZSA; - m_sigLgZSA = sigLgZSA; - m_uLgZSD = uLgZSD; - m_sigLgZSD = sigLgZSD; - m_offsetZOD = offsetZOD; - m_cDS = cDS; - m_cASD = cASD; - m_cASA = cASA; - m_cZSA = cZSA; - m_uK = uK; - m_sigK = sigK; - m_rTau = rTau; - m_shadowingStd = shadowingStd; - } - -}; - -/** - * \brief This class implements the fading computation of the 3GPP TR 38.900 channel model and performs the - * beamforming gain computation. It implements the SpectrumPropagationLossModel interface - */ -class MmWaveVehicularSpectrumPropagationLossModel : public SpectrumPropagationLossModel -{ -public: - /** -* Constructor -*/ - MmWaveVehicularSpectrumPropagationLossModel (); - /** - * Destructor - */ - virtual ~MmWaveVehicularSpectrumPropagationLossModel (); - - // inherited from Object - static TypeId GetTypeId (void); - void DoDispose (); - - /** - * Add a device - * @param a pointer to the NetDevice - * @param a pointer to the associated MmWaveVehicularAntennaArrayModel - */ - void AddDevice (Ptr, Ptr); - - /** - * Set the pathloss model associated to this class - * @param a pointer to the pathloss model, which has to implement the PropagationLossModel interface - */ - void SetPathlossModel (Ptr pathloss); - - /** - * \param freq the operating frequency (Hz) - */ - void SetFrequency (double freq); - - /** - * \returns the current frequency (Hz) - */ - double GetFrequency (void) const; - - -private: - /** - * Inherited from SpectrumPropagationLossModel, it returns the PSD at the receiver - * @params the transmitted PSD - * @params the mobility model of the transmitter - * @params the mobility model of the receiver - * @returns the received PSD - */ - Ptr DoCalcRxPowerSpectralDensity (Ptr txPsd, - Ptr a, - Ptr b) const; - - /** - * Get a new realization of the channel - * @params the ParamsTable for the specific scenario - * @params the location of UT - * @params the channel condition - * @params the o2i condition - * @params the ArrayAntennaModel for the txAntenna - * @params the ArrayAntennaModel for the rxAntenna - * @params the number of txAntenna per row - * @params the number of rxAntenna per row - * @params the rxAngle - * @params the txAngle - * @params the relative speed between tx and rx - * @params the 2D distance between tx and rx - * @params the 3D distance between tx and rx - * @returns the channel realization in a Params3gpp object - */ - Ptr GetNewChannel (Ptr table3gpp, Vector locUT, char condition, bool o2i, - Ptr txAntenna, Ptr rxAntenna, - uint16_t *txAntennaNum, uint16_t *rxAntennaNum, Angles &rxAngle, Angles &txAngle, - Vector speed, double dis2D, double dis3D) const; - - /** - * Update the channel realization with procedure A of TR 38.900 Sec 7.6.3.2 - * for the spatial consistency - * @params the previous channel realization in a Params3gpp object - * @params the ParamsTable for the specific scenario - * @params the ArrayAntennaModel for the txAntenna - * @params the ArrayAntennaModel for the rxAntenna - * @params the number of txAntenna per row - * @params the number of rxAntenna per row - * @params the rxAngle - * @params the txAngle - * @returns the channel realization in a Params3gpp object - */ - Ptr UpdateChannel (Ptr params3gpp, Ptr table3gpp, - Ptr txAntenna, Ptr rxAntenna, - uint16_t *txAntennaNum, uint16_t *rxAntennaNum, Angles &rxAngle, Angles &txAngle) const; - - /** - * Compute and return the long term fading params in order to decrease the computational load - * @params the channel realizationin as a Params3gpp object - * @return the complexVector_t with the BF applied to the channel - */ - complexVector_t CalLongTerm (Ptr params) const; - - /** - * Compute the BF gain, apply frequency selectivity by phase-shifting with the cluster delays - * and scale the txPsd to get the rxPsd - * @params the tx PSD - * @params the channel realizationin as a Params3gpp object - * @params the longTerm component (i.e., with the BF vectors already applied) - * @params the speed of the receivers - * @params the speed of the transmitter (for example in case of vehicular communication) - * @returns the rx PSD - */ - Ptr CalBeamformingGain (Ptr txPsd, - Ptr params, - complexVector_t longTerm, - Vector rxSpeed, - Vector txSpeed) const; - - /** - * Returns the loss associated to the oxygen absorption as described in p. 43 of TR 38.901 - * @returns a double corresponding to the loss associated to the oxygen absorption - * @params frequency of the subcarrier - * @params 3D distance between the communicating terminals - * @params delay associated to the cluster for which we are evaluating the loss - * @params 0 if in LOS condition and, if not, minimum delay among all clusters - */ - double GetOxygenLoss (double frequency, - double dist3D, - double tau, - double tauDelta) const; - - /** - * Returns the bandwidth used in a scenario - * @returns a double with the bandwidth - */ - double GetSystemBandwidth () const; - - /** - * Returns the ParamsTable with the parameters of TR 38.900 Table 7.5-6 - * that apply to a certain scenario - * @params the channel condition - * @params the o2i condition - * @params the BS height (i.e., eNB) - * @params the UT height (i.e., UE) - * @params the 2D distance - * @return the ParamsTable structure - */ - Ptr Get3gppTable (char condition, bool o2i, - double hBS, double hUT, double distance2D) const; - - /** - * Delete the m_channel entry associated to the Params3gpp object of pair (a,b) - * but keep the other parameters, so that the spatial consistency procedure can be used - * @params the mobility model of the transmitter - * @params the mobility model of the receiver - */ - void DeleteChannel (Ptr a, - Ptr b) const; - /* - * Returns the attenuation of each cluster in dB after applying blockage model - * @params the channel realizationin as a Params3gpp object - * @params cluster azimuth angle of arrival - * @params cluster zenith angle of arrival - */ - doubleVector_t CalAttenuationOfBlockage (Ptr params, - doubleVector_t clusterAOA, doubleVector_t clusterZOA) const; - - mutable std::map< key_t, Ptr > m_channelMap; - - double m_frequency; // operating frequency in Hz - - Ptr m_uniformRv; - Ptr m_uniformRvBlockage; - - Ptr m_normalRv; //there is a bug in the NormalRandomVariable::GetValue() function. - Ptr m_normalRvBlockage; - - Ptr m_expRv; - - Ptr m_3gppPathloss; - Ptr m_table3gpp; - Time m_updatePeriod; - bool m_blockage; - uint16_t m_numNonSelfBloking; //number of non-self-blocking regions. - bool m_portraitMode; //true (portrait mode); false (landscape mode). - bool m_oxygenAbsorption; //true (consider oxygen absorption); false (do not consider oxygen absorption effects - default). - std::string m_scenario; - double m_blockerSpeed; - bool m_interferenceOrDataMode; - bool m_o2i; // true if outdoor to indoor propagation - - std::map < Ptr, Ptr > m_deviceAntennaMap; - -}; - - -} // namespace millicar -} // namespace ns3 - - -#endif /* MMWAVE_VEHICULAR_SPECTRUM_PROPAGATION_LOSS_MODEL_H_ */ diff --git a/test/mmwave-vehicular-interference-test.cc b/test/mmwave-vehicular-interference-test.cc index 8acb00a..8f4c6ab 100644 --- a/test/mmwave-vehicular-interference-test.cc +++ b/test/mmwave-vehicular-interference-test.cc @@ -27,8 +27,9 @@ #include "ns3/mmwave-spectrum-value-helper.h" #include "ns3/test.h" #include "ns3/applications-module.h" +#include "ns3/buildings-module.h" #include "ns3/internet-module.h" -#include "ns3/core-module.h" +#include "ns3/config.h" NS_LOG_COMPONENT_DEFINE ("MmWaveVehicularInterferenceTestSuite"); @@ -166,6 +167,7 @@ MmWaveVehicularInterferenceTestCase::StartTest (double txPower) // create and configure the helper Ptr helper = CreateObject (); helper->SetNumerology (3); + helper->SetChannelModelType ("Ideal"); NetDeviceContainer devs1 = helper->InstallMmWaveVehicularNetDevices (group1); NetDeviceContainer devs2 = helper->InstallMmWaveVehicularNetDevices (group2); @@ -238,7 +240,12 @@ MmWaveVehicularInterferenceTestCase::StartTest (double txPower) apps2 = client2.Install (group2.Get (0)); apps2.Start (startTime); apps2.Stop (endTime); - + + // Mandatory to install buildings helper even if there are no buildings, + // otherwise V2V-Urban scenario does not work + BuildingsHelper::Install (group1); + BuildingsHelper::Install (group2); + // --------------------------------- double kT_dBm_Hz = -174.0; // dBm/Hz diff --git a/test/mmwave-vehicular-rate-test.cc b/test/mmwave-vehicular-rate-test.cc index 1d7446a..d872571 100644 --- a/test/mmwave-vehicular-rate-test.cc +++ b/test/mmwave-vehicular-rate-test.cc @@ -26,9 +26,10 @@ #include "ns3/spectrum-helper.h" #include "ns3/mmwave-spectrum-value-helper.h" #include "ns3/test.h" +#include "ns3/buildings-module.h" #include "ns3/applications-module.h" #include "ns3/internet-module.h" -#include "ns3/core-module.h" +#include "ns3/config.h" NS_LOG_COMPONENT_DEFINE ("MmWaveVehicularRateTestSuite"); @@ -164,6 +165,7 @@ MmWaveVehicularRateTestCase::StartTest (uint8_t mcs) // create and configure the helper Ptr helper = CreateObject (); helper->SetNumerology (3); + helper->SetChannelModelType ("V2V-Urban"); NetDeviceContainer devs = helper->InstallMmWaveVehicularNetDevices (n); // Install the TCP/IP stack in the two nodes @@ -187,7 +189,11 @@ MmWaveVehicularRateTestCase::StartTest (uint8_t mcs) NS_LOG_DEBUG("IPv4 Address node 0: " << n.Get (0)->GetObject ()->GetAddress (1, 0).GetLocal ()); NS_LOG_DEBUG("IPv4 Address node 1: " << n.Get (1)->GetObject ()->GetAddress (1, 0).GetLocal ()); - + + // Mandatory to install buildings helper even if there are no buildings, + // otherwise V2V-Urban scenario does not work + BuildingsHelper::Install (n); + // // Create a UdpEchoServer application on node one. // diff --git a/test/mmwave-vehicular-spectrum-phy-test.cc b/test/mmwave-vehicular-spectrum-phy-test.cc index 180899c..6e6e096 100644 --- a/test/mmwave-vehicular-spectrum-phy-test.cc +++ b/test/mmwave-vehicular-spectrum-phy-test.cc @@ -131,8 +131,10 @@ MmWaveVehicularSpectrumPhyTestCase1::StartTest (double dist) rx_mm->SetPosition (Vector (distance, 0.0, 0.0)); // create the antenna - Ptr tx_am = CreateObject (); - Ptr rx_am = CreateObject (); + Ptr tx_aam = CreateObject (); + Ptr rx_aam = CreateObject (); + tx_aam->SetAntennaElement(CreateObject ()); + rx_aam->SetAntennaElement(CreateObject ()); // create the channel SpectrumChannelHelper sh = SpectrumChannelHelper::Default (); @@ -141,13 +143,13 @@ MmWaveVehicularSpectrumPhyTestCase1::StartTest (double dist) // create and configure the tx spectrum phy Ptr tx_ssp = CreateObject (); tx_ssp->SetMobility (tx_mm); - tx_ssp->SetAntenna (tx_am); + tx_ssp->SetAntenna (tx_aam); tx_ssp->SetChannel (sc); // create and configure the tx spectrum phy Ptr rx_ssp = CreateObject (); rx_ssp->SetMobility (rx_mm); - rx_ssp->SetAntenna (rx_am); + rx_ssp->SetAntenna (rx_aam); rx_ssp->SetChannel (sc); // add the rx spectrum phy instance to the spectrum channel diff --git a/wscript b/wscript deleted file mode 100644 index fbcc276..0000000 --- a/wscript +++ /dev/null @@ -1,52 +0,0 @@ -# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- - -# def options(opt): -# pass - -# def configure(conf): -# conf.check_nonfatal(header_name='stdint.h', define_name='HAVE_STDINT_H') - -def build(bld): - module = bld.create_ns3_module('millicar', ['core', 'propagation', 'spectrum', 'mmwave']) - module.source = [ - 'model/mmwave-vehicular.cc', - 'model/mmwave-vehicular-propagation-loss-model.cc', - 'model/mmwave-vehicular-spectrum-propagation-loss-model.cc', - 'model/mmwave-sidelink-spectrum-phy.cc', - 'model/mmwave-sidelink-spectrum-signal-parameters.cc', - 'model/mmwave-sidelink-phy.cc', - 'model/mmwave-sidelink-mac.cc', - 'model/mmwave-vehicular-net-device.cc', - 'model/mmwave-vehicular-antenna-array-model.cc', - 'helper/mmwave-vehicular-helper.cc', - 'helper/mmwave-vehicular-traces-helper.cc' - ] - - module_test = bld.create_ns3_module_test_library('millicar') - module_test.source = [ - 'test/mmwave-vehicular-spectrum-phy-test.cc', - 'test/mmwave-vehicular-rate-test.cc', - 'test/mmwave-vehicular-interference-test.cc' - ] - - headers = bld(features='ns3header') - headers.module = 'millicar' - headers.source = [ - 'model/mmwave-vehicular.h', - 'model/mmwave-vehicular-propagation-loss-model.h', - 'model/mmwave-vehicular-spectrum-propagation-loss-model.h', - 'model/mmwave-sidelink-spectrum-phy.h', - 'model/mmwave-sidelink-spectrum-signal-parameters.h', - 'model/mmwave-sidelink-phy.h', - 'model/mmwave-sidelink-mac.h', - 'model/mmwave-sidelink-sap.h', - 'model/mmwave-vehicular-net-device.h', - 'model/mmwave-vehicular-antenna-array-model.h', - 'helper/mmwave-vehicular-helper.h', - 'helper/mmwave-vehicular-traces-helper.h' - ] - - if bld.env.ENABLE_EXAMPLES: - bld.recurse('examples') - - # bld.ns3_python_bindings()