propagation: (merges !435) Channel condition model for vehicular scenarios
This work was done in collaboration with Zoraze Ali and Sandra Lagen.
This commit is contained in:
committed by
Tom Henderson
parent
29e691d342
commit
0891fa9118
@@ -54,6 +54,8 @@ us a note on ns-developers mailing list.</p>
|
||||
<h1>Changes from ns-3.32 to ns-3.33</h1>
|
||||
<h2>New API:</h2>
|
||||
<ul>
|
||||
<li>New <b>channel models based on 3GPP TR 37.885</b> have been added to support vehicular simulations.</li>
|
||||
<b>Time::RoundTo (unit)</b> allows time to be rounded to the nearest integer multiple of unit</li>
|
||||
<li><b>Time::RoundTo (unit)</b> allows time to be rounded to the nearest integer multiple of unit</li>
|
||||
<li><b>UdpClient now can report both transmitted and received bytes.</li>
|
||||
</ul>
|
||||
|
||||
20
examples/channel-models/examples-to-run.py
Normal file
20
examples/channel-models/examples-to-run.py
Normal file
@@ -0,0 +1,20 @@
|
||||
#! /usr/bin/env python3
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
# A list of C++ examples to run in order to ensure that they remain
|
||||
# buildable and runnable over time. Each tuple in the list contains
|
||||
#
|
||||
# (example_name, do_run, do_valgrind_run).
|
||||
#
|
||||
# See test.py for more information.
|
||||
cpp_examples = [
|
||||
("three-gpp-v2v-channel-example", "True", "True"),
|
||||
]
|
||||
|
||||
# A list of Python examples to run in order to ensure that they remain
|
||||
# runnable over time. Each tuple in the list contains
|
||||
#
|
||||
# (example_name, do_run).
|
||||
#
|
||||
# See test.py for more information.
|
||||
python_examples = []
|
||||
373
examples/channel-models/three-gpp-v2v-channel-example.cc
Normal file
373
examples/channel-models/three-gpp-v2v-channel-example.cc
Normal file
@@ -0,0 +1,373 @@
|
||||
/* -*- 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
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is an example on how to configure the channel model classes to simulate
|
||||
* a vehicular environment.
|
||||
* The channel condition is determined using the model specified in [1], Table 6.2-1.
|
||||
* The pathloss is determined using the model specified in [1], Table 6.2.1-1.
|
||||
* The model for the fast fading is the one described in 3GPP TR 38.901 v15.0.0,
|
||||
* the model parameters are those specified in [1], Table 6.2.3-1.
|
||||
*
|
||||
* This example generates the output file 'example-output.txt'. Each row of the
|
||||
* file is organized as follows:
|
||||
* Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState SNR[dB] Pathloss[dB]
|
||||
* We also provide a bash script which reads the output file and generates two
|
||||
* figures:
|
||||
* (i) map.gif, a GIF representing the simulation scenario and vehicle mobility;
|
||||
* (ii) snr.png, which represents the behavior of the SNR.
|
||||
*
|
||||
* [1] 3GPP TR 37.885, v15.3.0
|
||||
*/
|
||||
|
||||
#include "ns3/buildings-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include <fstream>
|
||||
#include "ns3/three-gpp-antenna-array-model.h"
|
||||
#include "ns3/three-gpp-spectrum-propagation-loss-model.h"
|
||||
#include "ns3/three-gpp-v2v-propagation-loss-model.h"
|
||||
#include "ns3/three-gpp-channel-model.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ThreeGppV2vChannelExample");
|
||||
|
||||
static Ptr<ThreeGppPropagationLossModel> m_propagationLossModel; //!< the PropagationLossModel object
|
||||
static Ptr<ThreeGppSpectrumPropagationLossModel> m_spectrumLossModel; //!< the SpectrumPropagationLossModel object
|
||||
static Ptr<ChannelConditionModel> m_condModel; //!< the ChannelConditionModel object
|
||||
|
||||
/**
|
||||
* Perform the beamforming using the DFT beamforming method
|
||||
* \param thisDevice the device performing the beamforming
|
||||
* \param thisAntenna the antenna object associated to thisDevice
|
||||
* \param otherDevice the device towards which point the beam
|
||||
*/
|
||||
static void
|
||||
DoBeamforming (Ptr<NetDevice> thisDevice, Ptr<ThreeGppAntennaArrayModel> thisAntenna, Ptr<NetDevice> otherDevice)
|
||||
{
|
||||
ThreeGppAntennaArrayModel::ComplexVector antennaWeights;
|
||||
|
||||
// retrieve the position of the two devices
|
||||
Vector aPos = thisDevice->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
|
||||
Vector bPos = otherDevice->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
|
||||
|
||||
// compute the azimuth and the elevation angles
|
||||
Angles completeAngle (bPos,aPos);
|
||||
|
||||
double hAngleRadian = fmod (completeAngle.phi, 2.0 * M_PI); // the azimuth angle
|
||||
if (hAngleRadian < 0)
|
||||
{
|
||||
hAngleRadian += 2.0 * M_PI;
|
||||
}
|
||||
double vAngleRadian = completeAngle.theta; // the elevation angle
|
||||
|
||||
// retrieve the number of antenna elements
|
||||
int totNoArrayElements = thisAntenna->GetNumberOfElements ();
|
||||
|
||||
// the total power is divided equally among the antenna elements
|
||||
double power = 1 / sqrt (totNoArrayElements);
|
||||
|
||||
// compute the antenna weights
|
||||
for (int ind = 0; ind < totNoArrayElements; ind++)
|
||||
{
|
||||
Vector loc = thisAntenna->GetElementLocation (ind);
|
||||
double phase = -2 * M_PI * (sin (vAngleRadian) * cos (hAngleRadian) * loc.x
|
||||
+ sin (vAngleRadian) * sin (hAngleRadian) * loc.y
|
||||
+ cos (vAngleRadian) * loc.z);
|
||||
antennaWeights.push_back (exp (std::complex<double> (0, phase)) * power);
|
||||
}
|
||||
|
||||
// store the antenna weights
|
||||
thisAntenna->SetBeamformingVector (antennaWeights);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the average SNR
|
||||
* \param txMob the tx mobility model
|
||||
* \param rxMob the rx mobility model
|
||||
* \param txPsd the PSD of the transmitting signal
|
||||
* \param noiseFigure the noise figure in dB
|
||||
*/
|
||||
static void
|
||||
ComputeSnr (Ptr<MobilityModel> txMob, Ptr<MobilityModel> rxMob, Ptr<const SpectrumValue> txPsd, double noiseFigure)
|
||||
{
|
||||
Ptr<SpectrumValue> rxPsd = txPsd->Copy ();
|
||||
|
||||
// check the channel condition
|
||||
Ptr<ChannelCondition> cond = m_condModel->GetChannelCondition (txMob, rxMob);
|
||||
|
||||
// apply the pathloss
|
||||
double propagationGainDb = m_propagationLossModel->CalcRxPower (0, txMob, rxMob);
|
||||
NS_LOG_DEBUG ("Pathloss " << -propagationGainDb << " dB");
|
||||
double propagationGainLinear = std::pow (10.0, (propagationGainDb) / 10.0);
|
||||
*(rxPsd) *= propagationGainLinear;
|
||||
|
||||
// apply the fast fading and the beamforming gain
|
||||
rxPsd = m_spectrumLossModel->CalcRxPowerSpectralDensity (rxPsd, txMob, rxMob);
|
||||
NS_LOG_DEBUG ("Average rx power " << 10 * log10 (Sum (*rxPsd) * 180e3) << " dB");
|
||||
|
||||
// create the noise psd
|
||||
// taken from lte-spectrum-value-helper
|
||||
const double kT_dBm_Hz = -174.0; // dBm/Hz
|
||||
double kT_W_Hz = std::pow (10.0, (kT_dBm_Hz - 30) / 10.0);
|
||||
double noiseFigureLinear = std::pow (10.0, noiseFigure / 10.0);
|
||||
double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
|
||||
Ptr<SpectrumValue> noisePsd = Create <SpectrumValue> (txPsd->GetSpectrumModel ());
|
||||
(*noisePsd) = noisePowerSpectralDensity;
|
||||
|
||||
// compute the SNR
|
||||
NS_LOG_DEBUG ("Average SNR " << 10 * log10 (Sum (*rxPsd) / Sum (*noisePsd)) << " dB");
|
||||
|
||||
// print the SNR and pathloss values in the snr-trace.txt file
|
||||
std::ofstream f;
|
||||
f.open ("example-output.txt", std::ios::out | std::ios::app);
|
||||
f << Simulator::Now ().GetSeconds () << " " // time [s]
|
||||
<< txMob->GetPosition ().x << " "
|
||||
<< txMob->GetPosition ().y << " "
|
||||
<< rxMob->GetPosition ().x << " "
|
||||
<< rxMob->GetPosition ().y << " "
|
||||
<< cond->GetLosCondition () << " " // channel state
|
||||
<< 10 * log10 (Sum (*rxPsd) / Sum (*noisePsd)) << " " // SNR [dB]
|
||||
<< -propagationGainDb << std::endl; // pathloss [dB]
|
||||
f.close ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a GNU-plottable file representig the buildings deployed in the
|
||||
* scenario
|
||||
* \param filename the name of the output file
|
||||
*/
|
||||
void
|
||||
PrintGnuplottableBuildingListToFile (std::string filename)
|
||||
{
|
||||
std::ofstream outFile;
|
||||
outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
|
||||
if (!outFile.is_open ())
|
||||
{
|
||||
NS_LOG_ERROR ("Can't open file " << filename);
|
||||
return;
|
||||
}
|
||||
uint32_t index = 0;
|
||||
for (BuildingList::Iterator it = BuildingList::Begin (); it != BuildingList::End (); ++it)
|
||||
{
|
||||
++index;
|
||||
Box box = (*it)->GetBoundaries ();
|
||||
outFile << "set object " << index
|
||||
<< " rect from " << box.xMin << "," << box.yMin
|
||||
<< " to " << box.xMax << "," << box.yMax
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
double frequency = 28.0e9; // operating frequency in Hz
|
||||
double txPow_dbm = 30.0; // tx power in dBm
|
||||
double noiseFigure = 9.0; // noise figure in dB
|
||||
Time simTime = Seconds (40); // simulation time
|
||||
Time timeRes = MilliSeconds (10); // time resolution
|
||||
std::string scenario = "V2V-Urban"; // 3GPP propagation scenario, V2V-Urban or V2V-Highway
|
||||
double vScatt = 0; // maximum speed of the vehicles in the scenario [m/s]
|
||||
double subCarrierSpacing = 60e3; // subcarrier spacing in kHz
|
||||
uint32_t numRb = 275; // number of resource blocks
|
||||
|
||||
CommandLine cmd (__FILE__);
|
||||
cmd.AddValue ("frequency", "operating frequency in Hz", frequency);
|
||||
cmd.AddValue ("txPow", "tx power in dBm", txPow_dbm);
|
||||
cmd.AddValue ("noiseFigure", "noise figure in dB", noiseFigure);
|
||||
cmd.AddValue ("scenario", "3GPP propagation scenario, V2V-Urban or V2V-Highway", scenario);
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// create the nodes
|
||||
NodeContainer nodes;
|
||||
nodes.Create (2);
|
||||
|
||||
// create the tx and rx devices
|
||||
Ptr<SimpleNetDevice> txDev = CreateObject<SimpleNetDevice> ();
|
||||
Ptr<SimpleNetDevice> rxDev = CreateObject<SimpleNetDevice> ();
|
||||
|
||||
// associate the nodes and the devices
|
||||
nodes.Get (0)->AddDevice (txDev);
|
||||
txDev->SetNode (nodes.Get (0));
|
||||
nodes.Get (1)->AddDevice (rxDev);
|
||||
rxDev->SetNode (nodes.Get (1));
|
||||
|
||||
// create the antenna objects and set their dimensions
|
||||
Ptr<ThreeGppAntennaArrayModel> txAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (2), "NumRows", UintegerValue (2), "BearingAngle", DoubleValue (-M_PI / 2));
|
||||
Ptr<ThreeGppAntennaArrayModel> rxAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (2), "NumRows", UintegerValue (2), "BearingAngle", DoubleValue (M_PI / 2));
|
||||
|
||||
Ptr<MobilityModel> txMob;
|
||||
Ptr<MobilityModel> rxMob;
|
||||
if (scenario == "V2V-Urban")
|
||||
{
|
||||
// 3GPP defines that the maximum speed in urban scenario is 60 km/h
|
||||
vScatt = 60 / 3.6;
|
||||
|
||||
// create a grid of buildings
|
||||
double buildingSizeX = 250 - 3.5 * 2 - 3; // m
|
||||
double buildingSizeY = 433 - 3.5 * 2 - 3; // m
|
||||
double streetWidth = 20; // m
|
||||
double buildingHeight = 10; // m
|
||||
uint32_t numBuildingsX = 2;
|
||||
uint32_t numBuildingsY = 2;
|
||||
double maxAxisX = (buildingSizeX + streetWidth) * numBuildingsX;
|
||||
double maxAxisY = (buildingSizeY + streetWidth) * numBuildingsY;
|
||||
|
||||
std::vector<Ptr<Building> > buildingVector;
|
||||
for (uint32_t buildingIdX = 0; buildingIdX < numBuildingsX; ++buildingIdX)
|
||||
{
|
||||
for (uint32_t buildingIdY = 0; buildingIdY < numBuildingsY; ++buildingIdY)
|
||||
{
|
||||
Ptr < Building > building;
|
||||
building = CreateObject<Building> ();
|
||||
|
||||
building->SetBoundaries (Box (buildingIdX * (buildingSizeX + streetWidth),
|
||||
buildingIdX * (buildingSizeX + streetWidth) + buildingSizeX,
|
||||
buildingIdY * (buildingSizeY + streetWidth),
|
||||
buildingIdY * (buildingSizeY + streetWidth) + buildingSizeY,
|
||||
0.0, buildingHeight));
|
||||
building->SetNRoomsX (1);
|
||||
building->SetNRoomsY (1);
|
||||
building->SetNFloors (1);
|
||||
buildingVector.push_back (building);
|
||||
}
|
||||
}
|
||||
|
||||
// set the mobility model
|
||||
double vTx = vScatt;
|
||||
double vRx = vScatt / 2;
|
||||
txMob = CreateObject<WaypointMobilityModel> ();
|
||||
rxMob = CreateObject<WaypointMobilityModel> ();
|
||||
Time nextWaypoint = Seconds (0.0);
|
||||
txMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, 1.0, 1.5)));
|
||||
nextWaypoint += Seconds ((maxAxisY - streetWidth) / 2 / vTx);
|
||||
txMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, maxAxisY / 2 - streetWidth / 2, 1.5)));
|
||||
nextWaypoint += Seconds ((maxAxisX - streetWidth) / 2 / vTx);
|
||||
txMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (0.0, maxAxisY / 2 - streetWidth / 2, 1.5)));
|
||||
nextWaypoint = Seconds (0.0);
|
||||
rxMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, 0.0, 1.5)));
|
||||
nextWaypoint += Seconds (maxAxisY / vRx);
|
||||
rxMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, maxAxisY, 1.5)));
|
||||
|
||||
nodes.Get (0)->AggregateObject (txMob);
|
||||
nodes.Get (1)->AggregateObject (rxMob);
|
||||
|
||||
// create the channel condition model
|
||||
m_condModel = CreateObject<ThreeGppV2vUrbanChannelConditionModel> ();
|
||||
|
||||
// create the propagation loss model
|
||||
m_propagationLossModel = CreateObject<ThreeGppV2vUrbanPropagationLossModel> ();
|
||||
}
|
||||
else if (scenario == "V2V-Highway")
|
||||
{
|
||||
// Two vehicles are travelling one behid the other with constant velocity
|
||||
// along the y axis. The distance between the two vehicles is 20 meters.
|
||||
|
||||
// 3GPP defines that the maximum speed in urban scenario is 140 km/h
|
||||
vScatt = 140 / 3.6;
|
||||
double vTx = vScatt;
|
||||
double vRx = vScatt / 2;
|
||||
|
||||
txMob = CreateObject<ConstantVelocityMobilityModel> ();
|
||||
rxMob = CreateObject<ConstantVelocityMobilityModel> ();
|
||||
txMob->GetObject<ConstantVelocityMobilityModel> ()->SetPosition (Vector (300.0, 20.0, 1.5));
|
||||
txMob->GetObject<ConstantVelocityMobilityModel> ()->SetVelocity (Vector (0.0, vTx, 0.0));
|
||||
rxMob->GetObject<ConstantVelocityMobilityModel> ()->SetPosition (Vector (300.0, 0.0, 1.5));
|
||||
rxMob->GetObject<ConstantVelocityMobilityModel> ()->SetVelocity (Vector (0.0, vRx, 0.0));
|
||||
|
||||
nodes.Get (0)->AggregateObject (txMob);
|
||||
nodes.Get (1)->AggregateObject (rxMob);
|
||||
|
||||
// create the channel condition model
|
||||
m_condModel = CreateObject<ThreeGppV2vHighwayChannelConditionModel> ();
|
||||
|
||||
// create the propagation loss model
|
||||
m_propagationLossModel = CreateObject<ThreeGppV2vHighwayPropagationLossModel> ();
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Unknown scenario");
|
||||
}
|
||||
|
||||
m_condModel->SetAttribute ("UpdatePeriod", TimeValue (MilliSeconds (100)));
|
||||
|
||||
m_propagationLossModel->SetAttribute ("Frequency", DoubleValue (frequency));
|
||||
m_propagationLossModel->SetAttribute ("ShadowingEnabled", BooleanValue (false));
|
||||
m_propagationLossModel->SetAttribute ("ChannelConditionModel", PointerValue (m_condModel));
|
||||
|
||||
// create the channel model
|
||||
Ptr<ThreeGppChannelModel> channelModel = CreateObject<ThreeGppChannelModel> ();
|
||||
channelModel->SetAttribute ("Scenario", StringValue (scenario));
|
||||
channelModel->SetAttribute ("Frequency", DoubleValue (frequency));
|
||||
channelModel->SetAttribute ("ChannelConditionModel", PointerValue (m_condModel));
|
||||
|
||||
// create the spectrum propagation loss model
|
||||
m_spectrumLossModel = CreateObjectWithAttributes<ThreeGppSpectrumPropagationLossModel> ("ChannelModel", PointerValue (channelModel));
|
||||
m_spectrumLossModel->SetAttribute ("vScatt", DoubleValue (vScatt));
|
||||
|
||||
// initialize the devices in the ThreeGppSpectrumPropagationLossModel
|
||||
m_spectrumLossModel->AddDevice (txDev, txAntenna);
|
||||
m_spectrumLossModel->AddDevice (rxDev, rxAntenna);
|
||||
|
||||
BuildingsHelper::Install (nodes);
|
||||
|
||||
// set the beamforming vectors
|
||||
DoBeamforming (txDev, txAntenna, rxDev);
|
||||
DoBeamforming (rxDev, rxAntenna, txDev);
|
||||
|
||||
// create the tx power spectral density
|
||||
Bands rbs;
|
||||
double freqSubBand = frequency;
|
||||
for (uint16_t n = 0; n < numRb; ++n)
|
||||
{
|
||||
BandInfo rb;
|
||||
rb.fl = freqSubBand;
|
||||
freqSubBand += subCarrierSpacing / 2;
|
||||
rb.fc = freqSubBand;
|
||||
freqSubBand += subCarrierSpacing / 2;
|
||||
rb.fh = freqSubBand;
|
||||
rbs.push_back (rb);
|
||||
}
|
||||
Ptr<SpectrumModel> spectrumModel = Create<SpectrumModel> (rbs);
|
||||
Ptr<SpectrumValue> txPsd = Create <SpectrumValue> (spectrumModel);
|
||||
double txPow_w = std::pow (10., (txPow_dbm - 30) / 10);
|
||||
double txPowDens = (txPow_w / (numRb * subCarrierSpacing));
|
||||
(*txPsd) = txPowDens;
|
||||
|
||||
for (int i = 0; i < simTime / timeRes; i++)
|
||||
{
|
||||
Simulator::Schedule (timeRes * i, &ComputeSnr, txMob, rxMob, txPsd, noiseFigure);
|
||||
}
|
||||
|
||||
// initialize the output file
|
||||
std::ofstream f;
|
||||
f.open ("example-output.txt", std::ios::out);
|
||||
f << "Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState SNR[dB] Pathloss[dB]" << std::endl;
|
||||
f.close ();
|
||||
|
||||
// print the list of buildings to file
|
||||
PrintGnuplottableBuildingListToFile ("buildings.txt");
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
}
|
||||
68
examples/channel-models/three-gpp-v2v-channel-example.sh
Normal file
68
examples/channel-models/three-gpp-v2v-channel-example.sh
Normal file
@@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 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
|
||||
|
||||
#
|
||||
# Plot the traces generated by three-gpp-vehicular-channel-condition-model-example
|
||||
#
|
||||
|
||||
cat >aa <<EOL
|
||||
set terminal gif animate delay 100
|
||||
set output 'map.gif'
|
||||
set view map
|
||||
set style fill transparent solid 0.5
|
||||
unset key
|
||||
set style fill transparent solid 0.35 noborder
|
||||
set style circle radius 5
|
||||
|
||||
do for [i=0:299] {
|
||||
set multiplot layout 1,2
|
||||
set zrange [i-1:i]
|
||||
set xrange [-25:600]
|
||||
set yrange [-25:1000]
|
||||
set xlabel 'X [m]'
|
||||
set ylabel 'Y [m]'
|
||||
set xtics
|
||||
set ytics
|
||||
load 'buildings.txt'
|
||||
splot 'example-output.txt' u 2:3:1 with circles lc rgb "blue", 'example-output.txt' u 4:5:1 with circles lc rgb "red"
|
||||
set object 101 rect from -25,-25 to 1400,1000 fc rgb "white"
|
||||
set xrange [i-0.001:i+0.001]
|
||||
set yrange [i-0.001:i+0.001]
|
||||
unset xlabel
|
||||
unset ylabel
|
||||
unset xtics
|
||||
unset ytics
|
||||
plot 'example-output.txt' using 1:1:1 with labels offset -10, 0, 'example-output.txt' using 1:1:6 with labels offset 10, 0
|
||||
unset object 101
|
||||
unset multiplot
|
||||
}
|
||||
|
||||
reset
|
||||
set terminal png
|
||||
set output 'snr.png'
|
||||
set xlabel 'Time [s]'
|
||||
set ylabel 'SNR [dB]'
|
||||
set xtics
|
||||
set ytics
|
||||
set grid
|
||||
set xrange [0:40]
|
||||
set yrange [-20:100]
|
||||
plot 'example-output.txt' u 1:7 w l
|
||||
EOL
|
||||
gnuplot aa
|
||||
rm aa
|
||||
# rm out.txt
|
||||
5
examples/channel-models/wscript
Normal file
5
examples/channel-models/wscript
Normal file
@@ -0,0 +1,5 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
obj = bld.create_ns3_program('three-gpp-v2v-channel-example', ['core', 'mobility', 'propagation', 'spectrum', 'antenna', 'buildings'])
|
||||
obj.source = 'three-gpp-v2v-channel-example.cc'
|
||||
@@ -107,6 +107,7 @@ beamwidth, and :math:`A_{max}` is the maximum attenuation in dB of the
|
||||
antenna. Note that this radiation pattern is independent of the inclination angle
|
||||
:math:`\theta`.
|
||||
|
||||
.. _sec-3gpp-antenna-model:
|
||||
-------------------------
|
||||
ThreeGppAntennaArrayModel
|
||||
-------------------------
|
||||
|
||||
@@ -16,7 +16,9 @@ The Buildings module provides:
|
||||
#. a container class with the definition of the most useful pathloss models and the correspondent variables called ``BuildingsPropagationLossModel``.
|
||||
#. a new propagation model (``HybridBuildingsPropagationLossModel``) working with the mobility model just introduced, that allows to model the phenomenon of indoor/outdoor propagation in the presence of buildings.
|
||||
#. a simplified model working only with Okumura Hata (``OhBuildingsPropagationLossModel``) considering the phenomenon of indoor/outdoor propagation in the presence of buildings.
|
||||
|
||||
#. a channel condition model (``BuildingsChannelConditionModel``) which determined the LOS/NLOS channel condition based on the ``Building`` objects deployed in the scenario.
|
||||
#. hybrid channel condition models (``ThreeGppV2vUrbanChannelConditionModel`` and ``ThreeGppV2vHighwayChannelConditionModel``) specifically designed to model vehicular environments (more information can be found in the :ref:`documentation of the propagation module <sec-3gpp-v2v-ch-cond>`)
|
||||
|
||||
The models have been designed with LTE in mind, though their implementation is in fact independent from any LTE-specific code, and can be used with other ns-3 wireless technologies as well (e.g., wifi, wimax).
|
||||
|
||||
The ``HybridBuildingsPropagationLossModel`` pathloss model included is obtained through a combination of several well known pathloss models in order to mimic different environmental scenarios such as urban, suburban and open areas. Moreover, the model considers both outdoor and indoor indoor and outdoor communication has to be included since HeNB might be installed either within building and either outside. In case of indoor communication, the model has to consider also the type of building in outdoor <-> indoor communication according to some general criteria such as the wall penetration losses of the common materials; moreover it includes some general configuration for the internal walls in indoor communications.
|
||||
@@ -267,4 +269,3 @@ The following pseudo-code illustrates how the different pathloss model elements
|
||||
L = OH + EWL
|
||||
|
||||
We note that OhBuildingsPropagationLossModel is a significant simplification with respect to HybridBuildingsPropagationLossModel, due to the fact that OH is used always. While this gives a less accurate model in some scenarios (especially below rooftop and indoor), it effectively avoids the issue of pathloss discontinuities that affects HybridBuildingsPropagationLossModel.
|
||||
|
||||
|
||||
@@ -168,13 +168,18 @@ for the wireless module that you are considering (lte, wifi, wimax,
|
||||
etc.), so please refer to the documentation of that model for specific
|
||||
instructions.
|
||||
|
||||
Building-aware channel condition model
|
||||
**************************************
|
||||
Building-aware channel condition models
|
||||
***************************************
|
||||
|
||||
The class BuildingsChannelConditionModel implements a `channel condition model <propagation.html#channelconditionmodel>`_
|
||||
which determines the LOS/NLOS channel state based on the buildings deployed in
|
||||
the scenario.
|
||||
|
||||
The classes ``ThreeGppV2vUrbanChannelConditionModel`` and
|
||||
``ThreeGppV2vHighwayChannelConditionModel`` implement hybrid channel condition
|
||||
models, specifically designed to model vehicular environments.
|
||||
More information can be found in the :ref:`documentation
|
||||
of the propagation module <sec-3gpp-v2v-ch-cond>`.
|
||||
|
||||
Main configurable attributes
|
||||
============================
|
||||
|
||||
@@ -38,4 +38,4 @@ plot "pos.txt" with circles lc rgb "blue"
|
||||
EOL
|
||||
gnuplot buildings.txt aa
|
||||
rm aa
|
||||
rm pos.txt
|
||||
rm pos.txt
|
||||
|
||||
@@ -55,6 +55,7 @@ Ptr<ChannelCondition>
|
||||
BuildingsChannelConditionModel::GetChannelCondition (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
Ptr<MobilityBuildingInfo> a1 = a->GetObject<MobilityBuildingInfo> ();
|
||||
Ptr<MobilityBuildingInfo> b1 = b->GetObject<MobilityBuildingInfo> ();
|
||||
NS_ASSERT_MSG ((a1 != nullptr) && (b1 != nullptr),
|
||||
@@ -68,35 +69,45 @@ BuildingsChannelConditionModel::GetChannelCondition (Ptr<const MobilityModel> a,
|
||||
|
||||
if (!isAIndoor && !isBIndoor) // a and b are outdoor
|
||||
{
|
||||
cond->SetO2iCondition (ChannelCondition::O2iConditionValue::O2O);
|
||||
|
||||
// The outdoor case, determine LOS/NLOS
|
||||
// The channel condition should be LOS if the line of sight is not blocked,
|
||||
// otherwise NLOS
|
||||
bool blocked = IsLineOfSightBlocked (a->GetPosition (), b->GetPosition ());
|
||||
NS_LOG_DEBUG ("a and b are outdoor, blocked " << blocked);
|
||||
if (!blocked)
|
||||
{
|
||||
NS_LOG_DEBUG ("Set LOS");
|
||||
cond->SetLosCondition (ChannelCondition::LosConditionValue::LOS);
|
||||
}
|
||||
else
|
||||
{
|
||||
cond->SetLosCondition (ChannelCondition::LosConditionValue::NLOS);
|
||||
}
|
||||
|
||||
}
|
||||
else if (isAIndoor && isBIndoor) // a and b are indoor
|
||||
{
|
||||
cond->SetO2iCondition (ChannelCondition::O2iConditionValue::I2I);
|
||||
|
||||
// Indoor case, determine is the two nodes are inside the same building
|
||||
// or not
|
||||
if (a1->GetBuilding () == b1->GetBuilding ())
|
||||
{
|
||||
NS_LOG_DEBUG ("a and b are indoor in the same building");
|
||||
cond->SetLosCondition (ChannelCondition::LosConditionValue::LOS);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("a and b are indoor in different buildings");
|
||||
cond->SetLosCondition (ChannelCondition::LosConditionValue::NLOS);
|
||||
}
|
||||
}
|
||||
else //outdoor to indoor case
|
||||
{
|
||||
cond->SetO2iCondition (ChannelCondition::O2iConditionValue::O2I);
|
||||
|
||||
NS_LOG_DEBUG ("a is indoor and b outdoor or viceversa");
|
||||
cond->SetLosCondition (ChannelCondition::LosConditionValue::NLOS);
|
||||
}
|
||||
|
||||
|
||||
207
src/buildings/model/three-gpp-v2v-channel-condition-model.cc
Normal file
207
src/buildings/model/three-gpp-v2v-channel-condition-model.cc
Normal file
@@ -0,0 +1,207 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 SIGNET Lab, Department of Information Engineering,
|
||||
* University of Padova
|
||||
* Copyright (c) 2020 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
|
||||
*
|
||||
* 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 "three-gpp-v2v-channel-condition-model.h"
|
||||
#include "ns3/mobility-model.h"
|
||||
#include "ns3/log.h"
|
||||
#include <ns3/building-list.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ThreeGppV2vChannelConditionModel");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ThreeGppV2vUrbanChannelConditionModel);
|
||||
|
||||
TypeId
|
||||
ThreeGppV2vUrbanChannelConditionModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::ThreeGppV2vUrbanChannelConditionModel")
|
||||
.SetParent<ThreeGppChannelConditionModel> ()
|
||||
.SetGroupName ("Buildings")
|
||||
.AddConstructor<ThreeGppV2vUrbanChannelConditionModel> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
ThreeGppV2vUrbanChannelConditionModel::ThreeGppV2vUrbanChannelConditionModel ()
|
||||
: ThreeGppChannelConditionModel ()
|
||||
{
|
||||
m_buildingsCcm = CreateObject<BuildingsChannelConditionModel> ();
|
||||
}
|
||||
|
||||
ThreeGppV2vUrbanChannelConditionModel::~ThreeGppV2vUrbanChannelConditionModel ()
|
||||
{}
|
||||
|
||||
double
|
||||
ThreeGppV2vUrbanChannelConditionModel::ComputePlos (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// determine if there is a building in between the tx and rx
|
||||
Ptr<ChannelCondition> cond = m_buildingsCcm->GetChannelCondition (a, b);
|
||||
NS_ASSERT_MSG (cond->IsO2o (), "The nodes should be outdoor");
|
||||
|
||||
double pLos = 0.0;
|
||||
if (cond->IsLos ())
|
||||
{
|
||||
// compute the 2D distance between a and b
|
||||
double distance2D = Calculate2dDistance (a->GetPosition (), b->GetPosition ());
|
||||
|
||||
// compute the LOS probability (see 3GPP TR 37.885, Table 6.2-1)
|
||||
pLos = std::min (1.0, 1.05 * exp (-0.0114 * distance2D));
|
||||
}
|
||||
|
||||
return pLos;
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppV2vUrbanChannelConditionModel::ComputePnlos (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// determine the NLOS due to buildings
|
||||
Ptr<ChannelCondition> cond = m_buildingsCcm->GetChannelCondition (a, b);
|
||||
NS_ASSERT_MSG (cond->IsO2o (), "The nodes should be outdoor");
|
||||
|
||||
double pNlos = 0.0;
|
||||
if (cond->IsNlos ())
|
||||
{
|
||||
pNlos = 1.0;
|
||||
}
|
||||
|
||||
return pNlos;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ThreeGppV2vHighwayChannelConditionModel);
|
||||
|
||||
TypeId
|
||||
ThreeGppV2vHighwayChannelConditionModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::ThreeGppV2vHighwayChannelConditionModel")
|
||||
.SetParent<ThreeGppChannelConditionModel> ()
|
||||
.SetGroupName ("Buildings")
|
||||
.AddConstructor<ThreeGppV2vHighwayChannelConditionModel> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
ThreeGppV2vHighwayChannelConditionModel::ThreeGppV2vHighwayChannelConditionModel ()
|
||||
: ThreeGppChannelConditionModel ()
|
||||
{
|
||||
m_buildingsCcm = CreateObject<BuildingsChannelConditionModel> ();
|
||||
ComputeChCond = std::bind (&ThreeGppV2vHighwayChannelConditionModel::GetChCondAndFixCallback, this,
|
||||
std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
|
||||
ThreeGppV2vHighwayChannelConditionModel::~ThreeGppV2vHighwayChannelConditionModel ()
|
||||
{}
|
||||
|
||||
double
|
||||
ThreeGppV2vHighwayChannelConditionModel::ComputePlos (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// determine if there is a building in between the tx and rx
|
||||
Ptr<ChannelCondition> cond = ComputeChCond (a, b);
|
||||
NS_ASSERT_MSG (cond->IsO2o (), "The nodes should be outdoor");
|
||||
|
||||
double pLos = 0.0;
|
||||
if (cond->IsLos ())
|
||||
{
|
||||
// compute the 2D distance between a and b
|
||||
double distance2D = Calculate2dDistance (a->GetPosition (), b->GetPosition ());
|
||||
|
||||
// compute the LOS probability (see 3GPP TR 37.885, Table 6.2-1)
|
||||
if (distance2D <= 475.0)
|
||||
{
|
||||
pLos = std::min (1.0, 2.1013e-6 * distance2D * distance2D - 0.002 * distance2D + 1.0193);
|
||||
}
|
||||
else
|
||||
{
|
||||
pLos = std::max (0.0, 0.54 - 0.001 * (distance2D - 475.0));
|
||||
}
|
||||
}
|
||||
|
||||
return pLos;
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppV2vHighwayChannelConditionModel::ComputePnlos (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// determine the NLOS due to buildings
|
||||
Ptr<ChannelCondition> cond = ComputeChCond (a, b);
|
||||
NS_ASSERT_MSG (cond->IsO2o (), "The nodes should be outdoor");
|
||||
|
||||
double pNlos = 0;
|
||||
if (cond->IsNlos ())
|
||||
{
|
||||
pNlos = 1.0;
|
||||
}
|
||||
|
||||
return pNlos;
|
||||
}
|
||||
|
||||
Ptr<ChannelCondition>
|
||||
ThreeGppV2vHighwayChannelConditionModel::GetChCondAndFixCallback (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b)
|
||||
{
|
||||
Ptr<ChannelCondition> cond;
|
||||
if (BuildingList::Begin () != BuildingList::End ())
|
||||
{
|
||||
ComputeChCond = std::bind (&ThreeGppV2vHighwayChannelConditionModel::GetChCondWithBuildings, this,
|
||||
std::placeholders::_1, std::placeholders::_2);
|
||||
cond = GetChCondWithBuildings (a, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
ComputeChCond = std::bind (&ThreeGppV2vHighwayChannelConditionModel::GetChCondWithNoBuildings, this,
|
||||
std::placeholders::_1, std::placeholders::_2);
|
||||
cond = GetChCondWithNoBuildings (a, b);
|
||||
}
|
||||
return cond;
|
||||
}
|
||||
|
||||
Ptr<ChannelCondition>
|
||||
ThreeGppV2vHighwayChannelConditionModel::GetChCondWithBuildings (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
Ptr<ChannelCondition> cond = m_buildingsCcm->GetChannelCondition (a, b);
|
||||
return cond;
|
||||
}
|
||||
|
||||
Ptr<ChannelCondition>
|
||||
ThreeGppV2vHighwayChannelConditionModel::GetChCondWithNoBuildings (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
Ptr<ChannelCondition> cond = CreateObject<ChannelCondition> ();
|
||||
cond->SetO2iCondition (ChannelCondition::O2iConditionValue::O2O);
|
||||
cond->SetLosCondition (ChannelCondition::LosConditionValue::LOS);
|
||||
return cond;
|
||||
}
|
||||
|
||||
} // end namespace ns3
|
||||
208
src/buildings/model/three-gpp-v2v-channel-condition-model.h
Normal file
208
src/buildings/model/three-gpp-v2v-channel-condition-model.h
Normal file
@@ -0,0 +1,208 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 SIGNET Lab, Department of Information Engineering,
|
||||
* University of Padova
|
||||
* Copyright (c) 2020 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
|
||||
*
|
||||
* 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 THREE_GPP_V2V_CHANNEL_CONDITION_MODEL
|
||||
#define THREE_GPP_V2V_CHANNEL_CONDITION_MODEL
|
||||
|
||||
#include "ns3/channel-condition-model.h"
|
||||
#include "buildings-channel-condition-model.h"
|
||||
#include <functional>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class MobilityModel;
|
||||
|
||||
/**
|
||||
* \ingroup buildings
|
||||
*
|
||||
* \brief Computes the channel condition for the V2V Urban scenario
|
||||
*
|
||||
* Computes the channel condition following the specifications for the
|
||||
* V2V Urban scenario reported in Table 6.2-1 of 3GPP TR 37.885.
|
||||
*
|
||||
* 3GPP TR 37.885 defines 3 different channel states for vehicular environments:
|
||||
* LOS, NLOS and NLOSv, the latter representing the case in which the LOS path is
|
||||
* blocked by other vehicles in the scenario. The document defines a probabilistic
|
||||
* model to determine if the channel state is LOS or NLOSv, while the NLOS state
|
||||
* is determined in a deterministic way based on the buildings deployed in the
|
||||
* scenario. For this reason, this class makes use of an instance of
|
||||
* BuildingsChannelConditionModel to determine if the LOS is obstructed by
|
||||
* buildings or not.
|
||||
*/
|
||||
class ThreeGppV2vUrbanChannelConditionModel : public ThreeGppChannelConditionModel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Get the type ID.
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* Constructor for the ThreeGppV2vUrbanChannelConditionModel class
|
||||
*/
|
||||
ThreeGppV2vUrbanChannelConditionModel ();
|
||||
|
||||
/**
|
||||
* Destructor for the ThreeGppV2vUrbanChannelConditionModel class
|
||||
*/
|
||||
virtual ~ThreeGppV2vUrbanChannelConditionModel () override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Compute the LOS probability as specified in Table Table 6.2-1 of 3GPP TR 37.885
|
||||
* for the V2V Urban scenario.
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the LOS probability
|
||||
*/
|
||||
virtual double ComputePlos (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const override;
|
||||
|
||||
/**
|
||||
* Compute the NLOS probability. It determines the presence of obstructions
|
||||
* between the tx and the rx based on the buildings deployed in the scenario.
|
||||
* It returns 1 if the LOS path is obstructed, 0 otherwise.
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the NLOS probability
|
||||
*/
|
||||
virtual double ComputePnlos (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const override;
|
||||
|
||||
Ptr<BuildingsChannelConditionModel> m_buildingsCcm; //!< used to determine the obstructions due to buildings
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup buildings
|
||||
*
|
||||
* \brief Computes the channel condition for the V2V Highway scenario
|
||||
*
|
||||
* Computes the channel condition following the specifications for the
|
||||
* V2V Highway scenario reported in Table 6.2-1 of 3GPP TR 37.885.
|
||||
*
|
||||
* 3GPP TR 37.885 defines 3 different channel states for vehicular environments:
|
||||
* LOS, NLOS and NLOSv, the latter representing the case in which the LOS path is
|
||||
* blocked by other vehicles in the scenario. The document defines a probabilistic
|
||||
* model to determine if the channel state is LOS or NLOSv, while the NLOS state
|
||||
* is determined in a deterministic way based on the buildings deployed in the
|
||||
* scenario. For this reason, this class makes use of an instance of
|
||||
* BuildingsChannelConditionModel to determine if the LOS is obstructed by
|
||||
* buildings or not.
|
||||
*/
|
||||
class ThreeGppV2vHighwayChannelConditionModel : public ThreeGppChannelConditionModel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Get the type ID.
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* Constructor for the ThreeGppV2vHighwayChannelConditionModel class
|
||||
*/
|
||||
ThreeGppV2vHighwayChannelConditionModel ();
|
||||
|
||||
/**
|
||||
* Destructor for the ThreeGppV2vHighwayChannelConditionModel class
|
||||
*/
|
||||
virtual ~ThreeGppV2vHighwayChannelConditionModel () override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Compute the LOS probability as specified in Table Table 6.2-1 of 3GPP TR 37.885
|
||||
* for the V2V Highway scenario.
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the LOS probability
|
||||
*/
|
||||
virtual double ComputePlos (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const override;
|
||||
|
||||
/**
|
||||
* Compute the NLOS probability. It determines the presence of obstructions
|
||||
* between the tx and the rx based on the buildings deployed in the scenario.
|
||||
* It returns 1 if the LOS path is obstructed, 0 otherwise.
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the NLOS probability
|
||||
*/
|
||||
virtual double ComputePnlos (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const override;
|
||||
|
||||
/**
|
||||
* \brief The callback which is hooked to a method to compute channel condition.
|
||||
*
|
||||
* This callback is implemented to make this model robust against the
|
||||
* presence and absence of buildings in a highway scenario. If there are
|
||||
* buildings in a scenario, this model will use
|
||||
* \link BuildingsChannelConditionModel \endlink, which requires
|
||||
* \link MobilityBuildingInfo \endlink aggregated to the nodes to compute
|
||||
* LOS and NLOS. Otherwise, the callback is hooked to a local method
|
||||
* \link GetChaCondWithNoBuildings \endlink
|
||||
* , which construct the ChannelCondtion object and set the condition to
|
||||
* outdoor to outdoor with LOS.
|
||||
*/
|
||||
std::function <Ptr<ChannelCondition> (Ptr<const MobilityModel>, Ptr<const MobilityModel>) > ComputeChCond;
|
||||
|
||||
/**
|
||||
* \brief Get the channel condition and redirect the callback
|
||||
* \link ComputeChCond \endlink to \link GetChaCondWithBuildings \endlink
|
||||
* or to \link GetChaCondWithNoBuildings \endlink depending on if there are
|
||||
* buildings in the scenario or not.
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the the condition of the channel between \p a and \p b
|
||||
*/
|
||||
Ptr<ChannelCondition> GetChCondAndFixCallback (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b);
|
||||
|
||||
/**
|
||||
* \brief Get the channel condition between \p a and \p b
|
||||
* using BuildingsChannelConditionModel.
|
||||
*
|
||||
* This method will be called for the scenarios with buildings
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the condition of the channel between \p a and \p b
|
||||
*/
|
||||
Ptr<ChannelCondition> GetChCondWithBuildings (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const;
|
||||
|
||||
/**
|
||||
* \brief Get the channel condition between \p a and \p b
|
||||
*
|
||||
* This method will be called for the scenarios without buildings
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the condition of the channel between \p a and \p b
|
||||
*/
|
||||
Ptr<ChannelCondition> GetChCondWithNoBuildings (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const;
|
||||
|
||||
Ptr<BuildingsChannelConditionModel> m_buildingsCcm; //!< used to determine the obstructions due to buildings
|
||||
};
|
||||
|
||||
} // end ns3 namespace
|
||||
|
||||
#endif /* THREE_GPP_V2V_CHANNEL_CONDITION_MODEL */
|
||||
509
src/buildings/test/three-gpp-v2v-channel-condition-model-test.cc
Normal file
509
src/buildings/test/three-gpp-v2v-channel-condition-model-test.cc
Normal file
@@ -0,0 +1,509 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
|
||||
* Copyright (c) 2020 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
|
||||
*
|
||||
* 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/abort.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/buildings-channel-condition-model.h"
|
||||
#include "ns3/channel-condition-model.h"
|
||||
#include "ns3/three-gpp-v2v-channel-condition-model.h"
|
||||
#include "ns3/three-gpp-v2v-propagation-loss-model.h"
|
||||
#include "ns3/constant-position-mobility-model.h"
|
||||
#include "ns3/buildings-module.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/core-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ThreeGppV2vChannelConditionModelsTest");
|
||||
|
||||
/**
|
||||
* Test case for the classes ThreeGppV2vUrbanChannelConditionModel,
|
||||
* and ThreeGppV2vHighwayChannelConditionModel to test their code to
|
||||
* deterministically determine NLOS state. The test checks if the
|
||||
* channel condition is correctly determined when a building is deployed in the
|
||||
* scenario. Methodology from buildings-channel-condition-model-test.cc is used.
|
||||
*/
|
||||
class ThreeGppV2vBuildingsChCondModelTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppV2vBuildingsChCondModelTestCase ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreeGppV2vBuildingsChCondModelTestCase ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Builds the simulation scenario and perform the tests
|
||||
*/
|
||||
virtual void DoRun (void);
|
||||
|
||||
/**
|
||||
* Struct containing the parameters for each test
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Vector m_positionA; //!< the position of the first node
|
||||
Vector m_positionB; //!< the position of the second node
|
||||
ChannelCondition::LosConditionValue m_losCond; //!< the correct channel condition
|
||||
TypeId m_typeId; //!< the type ID of the channel condition model to be used
|
||||
} TestVector;
|
||||
|
||||
TestVectors<TestVector> m_testVectors; //!< array containg all the test vectors
|
||||
};
|
||||
|
||||
ThreeGppV2vBuildingsChCondModelTestCase::ThreeGppV2vBuildingsChCondModelTestCase ()
|
||||
: TestCase ("Test case for the ThreeGppV2vUrban and ThreeGppV2vHighway ChannelConditionModel with building"), m_testVectors ()
|
||||
{}
|
||||
|
||||
ThreeGppV2vBuildingsChCondModelTestCase::~ThreeGppV2vBuildingsChCondModelTestCase ()
|
||||
{}
|
||||
|
||||
void
|
||||
ThreeGppV2vBuildingsChCondModelTestCase::DoRun (void)
|
||||
{
|
||||
RngSeedManager::SetSeed (1);
|
||||
RngSeedManager::SetRun (1);
|
||||
|
||||
TestVector testVector;
|
||||
//Add vectors for ThreeGppV2vUrbanChannelConditionModel
|
||||
testVector.m_positionA = Vector (-5.0, 5.0, 1.5);
|
||||
testVector.m_positionB = Vector (20.0, 5.0, 1.5);
|
||||
testVector.m_losCond = ChannelCondition::LosConditionValue::NLOS;
|
||||
testVector.m_typeId = ThreeGppV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0.0, 11.0, 1.5);
|
||||
testVector.m_positionB = Vector (4.0, 11.0, 1.5);
|
||||
testVector.m_losCond = ChannelCondition::LosConditionValue::LOS;
|
||||
testVector.m_typeId = ThreeGppV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0.0, 11.0, 1.5);
|
||||
testVector.m_positionB = Vector (1000.0, 11.0, 1.5);
|
||||
testVector.m_losCond = ChannelCondition::LosConditionValue::NLOSv;
|
||||
testVector.m_typeId = ThreeGppV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
//Now add same vectors for ThreeGppV2vHighwayChannelConditionModel
|
||||
testVector.m_positionA = Vector (-5.0, 5.0, 1.5);
|
||||
testVector.m_positionB = Vector (20.0, 5.0, 1.5);
|
||||
testVector.m_losCond = ChannelCondition::LosConditionValue::NLOS;
|
||||
testVector.m_typeId = ThreeGppV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0.0, 11.0, 1.5);
|
||||
testVector.m_positionB = Vector (4.0, 11.0, 1.5);
|
||||
testVector.m_losCond = ChannelCondition::LosConditionValue::LOS;
|
||||
testVector.m_typeId = ThreeGppV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0.0, 11.0, 1.5);
|
||||
testVector.m_positionB = Vector (1000.0, 11.0, 1.5);
|
||||
testVector.m_losCond = ChannelCondition::LosConditionValue::NLOSv;
|
||||
testVector.m_typeId = ThreeGppV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
// create the factory for the channel condition models
|
||||
ObjectFactory condModelFactory;
|
||||
|
||||
// Deploy nodes and building and get the channel condition
|
||||
NodeContainer nodes;
|
||||
nodes.Create (2);
|
||||
|
||||
Ptr<MobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
|
||||
nodes.Get (0)->AggregateObject (a);
|
||||
|
||||
Ptr<MobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
|
||||
nodes.Get (1)->AggregateObject (b);
|
||||
|
||||
Ptr<Building> building = Create<Building> ();
|
||||
building->SetNRoomsX (1);
|
||||
building->SetNRoomsY (1);
|
||||
building->SetNFloors (1);
|
||||
building->SetBoundaries (Box (0.0, 10.0, 0.0, 10.0, 0.0, 5.0));
|
||||
|
||||
BuildingsHelper::Install (nodes);
|
||||
|
||||
for (uint32_t i = 0; i < m_testVectors.GetN (); ++i)
|
||||
{
|
||||
testVector = m_testVectors.Get (i);
|
||||
condModelFactory.SetTypeId (testVector.m_typeId);
|
||||
Ptr<ChannelConditionModel> condModel = DynamicCast<ChannelConditionModel> (condModelFactory.Create ());
|
||||
condModel->AssignStreams (1);
|
||||
|
||||
a->SetPosition (testVector.m_positionA);
|
||||
b->SetPosition (testVector.m_positionB);
|
||||
Ptr<MobilityBuildingInfo> buildingInfoA = a->GetObject<MobilityBuildingInfo> ();
|
||||
buildingInfoA->MakeConsistent (a);
|
||||
Ptr<MobilityBuildingInfo> buildingInfoB = b->GetObject<MobilityBuildingInfo> ();
|
||||
buildingInfoB->MakeConsistent (b);
|
||||
Ptr<ChannelCondition> cond;
|
||||
cond = condModel->GetChannelCondition (a, b);
|
||||
|
||||
NS_LOG_DEBUG ("Got " << cond->GetLosCondition () << " expected condition " << testVector.m_losCond);
|
||||
NS_TEST_ASSERT_MSG_EQ (cond->GetLosCondition (), testVector.m_losCond, "Got unexpected channel condition");
|
||||
}
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case for the 3GPP V2V Urban channel condition models (probabilistic
|
||||
* model for LOS/NLOSv states). It determines the channel condition multiple times,
|
||||
* estimates the LOS probability and compares it with the value given by the
|
||||
* formulas in 3GPP TR 37.885, Table 6.2-1. Methodology from channel-condition-model-
|
||||
* test-suite.cc is used.
|
||||
*/
|
||||
class ThreeGppV2vUrbanLosNlosvChCondModelTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppV2vUrbanLosNlosvChCondModelTestCase ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreeGppV2vUrbanLosNlosvChCondModelTestCase ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Builds the simulation scenario and perform the tests
|
||||
*/
|
||||
virtual void DoRun (void);
|
||||
|
||||
/**
|
||||
* Evaluates the channel condition between two nodes by calling the method
|
||||
* GetChannelCondition on m_condModel. If the channel condition is LOS it
|
||||
* increments m_numLos
|
||||
* \param a the mobility model of the first node
|
||||
* \param b the mobility model of the second node
|
||||
*/
|
||||
void EvaluateChannelCondition (Ptr<MobilityModel> a, Ptr<MobilityModel> b);
|
||||
|
||||
/**
|
||||
* Struct containing the parameters for each test
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Vector m_positionA; //!< the position of the first node
|
||||
Vector m_positionB; //!< the position of the second node
|
||||
double m_pLos; //!< LOS probability
|
||||
TypeId m_typeId; //!< the type ID of the channel condition model to be used
|
||||
} TestVector;
|
||||
|
||||
TestVectors<TestVector> m_testVectors; //!< array containing all the test vectors
|
||||
Ptr<ThreeGppV2vUrbanChannelConditionModel> m_condModel; //!< the channel condition model
|
||||
uint64_t m_numLos {0}; //!< the number of LOS occurrences
|
||||
double m_tolerance; //!< tolerance
|
||||
};
|
||||
|
||||
ThreeGppV2vUrbanLosNlosvChCondModelTestCase::ThreeGppV2vUrbanLosNlosvChCondModelTestCase ()
|
||||
: TestCase ("Test case for the class ThreeGppV2vUrbanChannelConditionModel"),
|
||||
m_testVectors (),
|
||||
m_tolerance (2e-3)
|
||||
{}
|
||||
|
||||
ThreeGppV2vUrbanLosNlosvChCondModelTestCase::~ThreeGppV2vUrbanLosNlosvChCondModelTestCase ()
|
||||
{}
|
||||
|
||||
void
|
||||
ThreeGppV2vUrbanLosNlosvChCondModelTestCase::EvaluateChannelCondition (Ptr<MobilityModel> a, Ptr<MobilityModel> b)
|
||||
{
|
||||
Ptr<ChannelCondition> cond = m_condModel->GetChannelCondition (a, b);
|
||||
if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::LOS)
|
||||
{
|
||||
m_numLos++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppV2vUrbanLosNlosvChCondModelTestCase::DoRun (void)
|
||||
{
|
||||
RngSeedManager::SetSeed (1);
|
||||
RngSeedManager::SetRun (1);
|
||||
|
||||
// create the test vector
|
||||
TestVector testVector;
|
||||
|
||||
// tests for the V2v Urban scenario
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (10, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, 1.05 * exp (-0.0114 * 10.0));
|
||||
testVector.m_typeId = ThreeGppV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (100, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, 1.05 * exp (-0.0114 * 100.0));
|
||||
testVector.m_typeId = ThreeGppV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (1000, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, 1.05 * exp (-0.0114 * 1000.0));
|
||||
testVector.m_typeId = ThreeGppV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
// create the factory for the channel condition models
|
||||
ObjectFactory condModelFactory;
|
||||
|
||||
// create the two nodes
|
||||
NodeContainer nodes;
|
||||
nodes.Create (2);
|
||||
|
||||
// create the mobility models
|
||||
Ptr<MobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
|
||||
Ptr<MobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
|
||||
|
||||
// aggregate the nodes and the mobility models
|
||||
nodes.Get (0)->AggregateObject (a);
|
||||
nodes.Get (1)->AggregateObject (b);
|
||||
|
||||
BuildingsHelper::Install (nodes);
|
||||
|
||||
// Get the channel condition multiple times and compute the LOS probability
|
||||
uint32_t numberOfReps = 500000;
|
||||
for (uint32_t i = 0; i < m_testVectors.GetN (); ++i)
|
||||
{
|
||||
testVector = m_testVectors.Get (i);
|
||||
|
||||
// set the distance between the two nodes
|
||||
a->SetPosition (testVector.m_positionA);
|
||||
b->SetPosition (testVector.m_positionB);
|
||||
Ptr<MobilityBuildingInfo> buildingInfoA = a->GetObject<MobilityBuildingInfo> ();
|
||||
buildingInfoA->MakeConsistent (a);
|
||||
Ptr<MobilityBuildingInfo> buildingInfoB = b->GetObject<MobilityBuildingInfo> ();
|
||||
buildingInfoB->MakeConsistent (b);
|
||||
|
||||
// create the channel condition model
|
||||
condModelFactory.SetTypeId (testVector.m_typeId);
|
||||
m_condModel = condModelFactory.Create<ThreeGppV2vUrbanChannelConditionModel> ();
|
||||
m_condModel->SetAttribute ("UpdatePeriod", TimeValue (MilliSeconds (9)));
|
||||
m_condModel->AssignStreams (1);
|
||||
|
||||
m_numLos = 0;
|
||||
for (uint32_t j = 0; j < numberOfReps; j++)
|
||||
{
|
||||
Simulator::Schedule (MilliSeconds (10 * j), &ThreeGppV2vUrbanLosNlosvChCondModelTestCase::EvaluateChannelCondition, this, a, b);
|
||||
}
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
double resultPlos = double (m_numLos) / double (numberOfReps);
|
||||
NS_LOG_DEBUG (testVector.m_typeId << " a pos " << testVector.m_positionA << " b pos " << testVector.m_positionB << " numLos " << m_numLos << " numberOfReps " << numberOfReps << " resultPlos " << resultPlos << " ref " << testVector.m_pLos);
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (resultPlos, testVector.m_pLos, m_tolerance, "Got unexpected LOS probability");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case for the 3GPP V2V Highway channel condition models (probabilistic
|
||||
* model for LOS/NLOSv states). It determines the channel condition multiple times,
|
||||
* estimates the LOS probability and compares it with the value given by the
|
||||
* formulas in 3GPP TR 37.885, Table 6.2-1. Methodology from channel-condition-model-
|
||||
* test-suite.cc is used.
|
||||
*/
|
||||
class ThreeGppV2vHighwayLosNlosvChCondModelTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppV2vHighwayLosNlosvChCondModelTestCase ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreeGppV2vHighwayLosNlosvChCondModelTestCase ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Builds the simulation scenario and perform the tests
|
||||
*/
|
||||
virtual void DoRun (void);
|
||||
|
||||
/**
|
||||
* Evaluates the channel condition between two nodes by calling the method
|
||||
* GetChannelCondition on m_condModel. If the channel condition is LOS it
|
||||
* increments m_numLos
|
||||
* \param a the mobility model of the first node
|
||||
* \param b the mobility model of the second node
|
||||
*/
|
||||
void EvaluateChannelCondition (Ptr<MobilityModel> a, Ptr<MobilityModel> b);
|
||||
|
||||
/**
|
||||
* Struct containing the parameters for each test
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Vector m_positionA; //!< the position of the first node
|
||||
Vector m_positionB; //!< the position of the second node
|
||||
double m_pLos; //!< LOS probability
|
||||
TypeId m_typeId; //!< the type ID of the channel condition model to be used
|
||||
} TestVector;
|
||||
|
||||
TestVectors<TestVector> m_testVectors; //!< array containing all the test vectors
|
||||
Ptr<ThreeGppV2vHighwayChannelConditionModel> m_condModel; //!< the channel condition model
|
||||
uint64_t m_numLos {0}; //!< the number of LOS occurrences
|
||||
double m_tolerance; //!< tolerance
|
||||
};
|
||||
|
||||
ThreeGppV2vHighwayLosNlosvChCondModelTestCase::ThreeGppV2vHighwayLosNlosvChCondModelTestCase ()
|
||||
: TestCase ("Test case for the class ThreeGppV2vHighwayChannelConditionModel"),
|
||||
m_testVectors (),
|
||||
m_tolerance (2e-3)
|
||||
{}
|
||||
|
||||
ThreeGppV2vHighwayLosNlosvChCondModelTestCase::~ThreeGppV2vHighwayLosNlosvChCondModelTestCase ()
|
||||
{}
|
||||
|
||||
void
|
||||
ThreeGppV2vHighwayLosNlosvChCondModelTestCase::EvaluateChannelCondition (Ptr<MobilityModel> a, Ptr<MobilityModel> b)
|
||||
{
|
||||
Ptr<ChannelCondition> cond = m_condModel->GetChannelCondition (a, b);
|
||||
if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::LOS)
|
||||
{
|
||||
m_numLos++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppV2vHighwayLosNlosvChCondModelTestCase::DoRun (void)
|
||||
{
|
||||
RngSeedManager::SetSeed (1);
|
||||
RngSeedManager::SetRun (1);
|
||||
|
||||
// create the test vector
|
||||
TestVector testVector;
|
||||
|
||||
// tests for the V2v Highway scenario
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (10, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, 0.0000021013 * 10.0 * 10.0 - 0.002 * 10.0 + 1.0193);
|
||||
testVector.m_typeId = ThreeGppV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (100, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, 0.0000021013 * 100.0 * 100.0 - 0.002 * 100.0 + 1.0193);
|
||||
testVector.m_typeId = ThreeGppV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (1000, 0, 1.6);
|
||||
testVector.m_pLos = std::max (0.0, 0.54 - 0.001 * (1000.0 - 475));
|
||||
testVector.m_typeId = ThreeGppV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
// create the factory for the channel condition models
|
||||
ObjectFactory condModelFactory;
|
||||
|
||||
// create the two nodes
|
||||
NodeContainer nodes;
|
||||
nodes.Create (2);
|
||||
|
||||
// create the mobility models
|
||||
Ptr<MobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
|
||||
Ptr<MobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
|
||||
|
||||
// aggregate the nodes and the mobility models
|
||||
nodes.Get (0)->AggregateObject (a);
|
||||
nodes.Get (1)->AggregateObject (b);
|
||||
|
||||
BuildingsHelper::Install (nodes);
|
||||
|
||||
// Get the channel condition multiple times and compute the LOS probability
|
||||
uint32_t numberOfReps = 500000;
|
||||
for (uint32_t i = 0; i < m_testVectors.GetN (); ++i)
|
||||
{
|
||||
testVector = m_testVectors.Get (i);
|
||||
|
||||
// set the distance between the two nodes
|
||||
a->SetPosition (testVector.m_positionA);
|
||||
b->SetPosition (testVector.m_positionB);
|
||||
|
||||
// create the channel condition model
|
||||
condModelFactory.SetTypeId (testVector.m_typeId);
|
||||
m_condModel = condModelFactory.Create<ThreeGppV2vHighwayChannelConditionModel> ();
|
||||
m_condModel->SetAttribute ("UpdatePeriod", TimeValue (MilliSeconds (9)));
|
||||
m_condModel->AssignStreams (1);
|
||||
|
||||
m_numLos = 0;
|
||||
for (uint32_t j = 0; j < numberOfReps; j++)
|
||||
{
|
||||
Simulator::Schedule (MilliSeconds (10 * j), &ThreeGppV2vHighwayLosNlosvChCondModelTestCase::EvaluateChannelCondition, this, a, b);
|
||||
}
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
double resultPlos = static_cast<double> (m_numLos) / static_cast<double> (numberOfReps);
|
||||
NS_LOG_DEBUG (testVector.m_typeId << " a pos " << testVector.m_positionA << " b pos " << testVector.m_positionB << " numLos " << m_numLos << " numberOfReps " << numberOfReps << " resultPlos " << resultPlos << " ref " << testVector.m_pLos);
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (resultPlos, testVector.m_pLos, m_tolerance, "Got unexpected LOS probability");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test suite for the 3GPP V2V channel condition model
|
||||
*
|
||||
* Note that, in 3GPP V2V scenarios, the channel condition model is
|
||||
* determined based on a two step procedure: 1st) NLOS state is determined
|
||||
* based on a deterministic model (using buildings), and 2nd) the LOS or NLOSv
|
||||
* state is determined based on a probabilistic model (using 3GPP formulas), in
|
||||
* case that the vehicles are not in NLOS condition.
|
||||
*
|
||||
* The test ThreeGppV2vBuildingsChCondModelTestCase checks the
|
||||
* 1st step of the procedure, the deterministic one, using buildings for
|
||||
* both \link ThreeGppV2vUrbanChannelConditionModel \endlink and
|
||||
* \link ThreeGppV2vHighwayChannelConditionModel \endlink .
|
||||
*
|
||||
* The tests ThreeGppV2vUrbanLosNlosvChCondModelTestCase and
|
||||
* ThreeGppV2vHighwayLosNlosvChCondModelTestCase check the
|
||||
* 2nd step of the procedure, the probabilistic one, without buildings, for
|
||||
* the V2V Urban and V2V Highway scenarios, respectively.
|
||||
*
|
||||
*/
|
||||
class ThreeGppV2vChCondModelsTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
ThreeGppV2vChCondModelsTestSuite ();
|
||||
};
|
||||
|
||||
ThreeGppV2vChCondModelsTestSuite::ThreeGppV2vChCondModelsTestSuite ()
|
||||
: TestSuite ("three-gpp-v2v-channel-condition-model", SYSTEM)
|
||||
{
|
||||
AddTestCase (new ThreeGppV2vBuildingsChCondModelTestCase, TestCase::QUICK); // test for the deterministic procedure (NLOS vs LOS/NLOSv), based on buildings
|
||||
AddTestCase (new ThreeGppV2vUrbanLosNlosvChCondModelTestCase, TestCase::QUICK); // test for the probabilistic procedure (LOS vs NLOSv), in V2V urban scenario
|
||||
AddTestCase (new ThreeGppV2vHighwayLosNlosvChCondModelTestCase, TestCase::QUICK); // test for the probabilistic procedure (LOS vs NLOSv), in V2V highway scenario
|
||||
}
|
||||
|
||||
static ThreeGppV2vChCondModelsTestSuite ThreeGppV2vChCondModelsTestSuite;
|
||||
@@ -12,6 +12,7 @@ def build(bld):
|
||||
'model/hybrid-buildings-propagation-loss-model.cc',
|
||||
'model/oh-buildings-propagation-loss-model.cc',
|
||||
'model/buildings-channel-condition-model.cc',
|
||||
'model/three-gpp-v2v-channel-condition-model.cc',
|
||||
'helper/building-container.cc',
|
||||
'helper/building-position-allocator.cc',
|
||||
'helper/building-allocator.cc',
|
||||
@@ -27,6 +28,7 @@ def build(bld):
|
||||
'test/buildings-shadowing-test.cc',
|
||||
'test/buildings-channel-condition-model-test.cc',
|
||||
'test/outdoor-random-walk-test.cc',
|
||||
'test/three-gpp-v2v-channel-condition-model-test.cc',
|
||||
]
|
||||
|
||||
# Tests encapsulating example programs should be listed here
|
||||
@@ -46,6 +48,7 @@ def build(bld):
|
||||
'model/hybrid-buildings-propagation-loss-model.h',
|
||||
'model/oh-buildings-propagation-loss-model.h',
|
||||
'model/buildings-channel-condition-model.h',
|
||||
'model/three-gpp-v2v-channel-condition-model.h',
|
||||
'helper/building-container.h',
|
||||
'helper/building-allocator.h',
|
||||
'helper/building-position-allocator.h',
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
Propagation
|
||||
-----------
|
||||
|
||||
The |ns3| propagation module defines two generic interfaces, namely :cpp:class:`PropagationLossModel`
|
||||
and :cpp:class:`PropagationDelayModel`, for the modeling of respectively propagation loss and propagation delay.
|
||||
The |ns3| ``propagation`` module defines two generic interfaces, namely :cpp:class:`PropagationLossModel`
|
||||
and :cpp:class:`PropagationDelayModel`, to model respectively the propagation loss and the propagation delay.
|
||||
|
||||
PropagationLossModel
|
||||
********************
|
||||
@@ -613,8 +613,8 @@ channel condition model related to the same scenario is set (e.g., by default,
|
||||
:cpp:class:`ThreeGppRmaPropagationLossModel` is paired with
|
||||
:cpp:class:`ThreeGppRmaChannelConditionModel`), but it can be configured using
|
||||
the method SetChannelConditionModel. The channel condition models are stored inside the
|
||||
propagation module, for a limitation of the current spectrum API and to avoid
|
||||
a circular dependency between the spectrum and the propagation modules. Please
|
||||
``propagation`` module, for a limitation of the current spectrum API and to avoid
|
||||
a circular dependency between the spectrum and the ``propagation`` modules. Please
|
||||
note that it is necessary to install at least one :cpp:class:`ChannelConditionModel` when
|
||||
using any :cpp:class:`ThreeGppPropagationLossModel` subclass. Please look below for more
|
||||
information about the Channel Condition models.
|
||||
@@ -802,6 +802,174 @@ The propagation delay is totally random, and it changes each time the model is c
|
||||
All the packets (even those between two fixed nodes) experience a random delay.
|
||||
As a consequence, the packets order is not preserved.
|
||||
|
||||
Models for vehicular environments
|
||||
*********************************
|
||||
|
||||
The 3GPP TR 37.885 [37885]_ specifications extends the channel modeling framework
|
||||
described in TR 38.901 [38901]_ to simulate wireless channels in vehicular environments.
|
||||
The extended framework supports frequencies between 0.5 to 100 GHz and provides
|
||||
the possibility to simulate urban and highway propagation environments.
|
||||
To do so, new propagation loss and channel condition models, as well as new
|
||||
parameters for the fast fading model, are provided.
|
||||
|
||||
.. _sec-3gpp-v2v-ch-cond:
|
||||
|
||||
Vehicular channel condition models
|
||||
==================================
|
||||
|
||||
To properly capture channel dynamics in vehicular environments, three different
|
||||
channel conditions have been identified:
|
||||
* LOS (Line Of Sight): represents the case in which the direct path between
|
||||
the transmitter and the receiver is not blocked
|
||||
* NLOSv (Non Line Of Sight vehicle): when the direct path
|
||||
between the transmitter and the receiver is blocked by a vehicle
|
||||
* NLOS (Non Line Of Sight): when the direct path is blocked by a building
|
||||
|
||||
TR 37.885 includes two models that can be used to determine the condition of
|
||||
the wireless channel between a pair of nodes, the first for urban and the second
|
||||
for highway environments.
|
||||
Each model includes both a deterministic and a stochastic part, and works as
|
||||
follows.
|
||||
1. The model determines the presence of buildings obstructing the direct path
|
||||
between the communicating nodes. This is done in a deterministic way, looking at
|
||||
the possible interceptions between the direct path and the buildings.
|
||||
If the path is obstructed, the channel condition is set to NLOS.
|
||||
2. If not, the model determines the presence of vehicles obstructing the
|
||||
direct path. This is done using a probabilistic model, which is specific
|
||||
for the scenario of interest. If the path is obstructed, the channel
|
||||
condition is set to NLOSv, otherwise is set to LOS.
|
||||
|
||||
These models have been implemented by extending the interface
|
||||
:cpp:class:`ChannelConditionModel` with the following classes. They have been included in
|
||||
the ``building`` module, because they make use of :cpp:class:`Buildings` objects to determine
|
||||
the presence of obstructions caused by buildings.
|
||||
* :cpp:class:`ThreeGppV2vUrbanChannelConditionModel`: implements the model
|
||||
described in Table 6.2-1 of TR 37.885 for the urban scenario.
|
||||
* :cpp:class:`ThreeGppV2vHighwayChannelConditionModel`: implements the model
|
||||
described in Table 6.2-1 of TR 37.885 for the highway scenario.
|
||||
These models rely on :cpp:class:`Buildings` objects to determine the presence
|
||||
of obstructing buildings. When considering large scenarios with a large number of
|
||||
buildings, this process may become computationally demanding and dramatically
|
||||
increase the simulation time.
|
||||
To solve this problem, we implemented two fully-probabilistic models
|
||||
that can be used as an alternative to the ones included in TR 37.885.
|
||||
These models are based on the work carried out by M. Boban et al. [Boban2016Modeling]_,
|
||||
which derived a statistical representation of the three channel conditions,
|
||||
With the fully-probabilistic models there is no need to determine the presence of blocking
|
||||
buildings in a deterministic way, and therefore the computational effort is
|
||||
reduced.
|
||||
To determine the channel condition, these models account for the propagation
|
||||
environment, i.e., urban or highway, as well as for the density of vehicles in the
|
||||
scenario, which can be high, medium, or low.
|
||||
|
||||
The classes implementing the fully-probabilistic models are:
|
||||
* :cpp:class:`ProbabilisticV2vUrbanChannelConditionModel`: implements the model
|
||||
described in [Boban2016Modeling]_ for the urban scenario.
|
||||
* :cpp:class:`ProbabilisticV2vHighwayChannelConditionModel`: implements the model
|
||||
described in [Boban2016Modeling]_ for the highway scenario.
|
||||
Both the classes own the attribute "Density", which can be used to select the
|
||||
proper value depending on the scenario that have to be simulated.
|
||||
Differently from the hybrid models described above, these classes have been
|
||||
included in the ``propagation`` module, since they do not have any dependency on the
|
||||
``building`` module.
|
||||
|
||||
**NOTE:** Both the hybrid and the fully-probabilistic models supports the
|
||||
modeling of outdoor scenarios, no support is provided for the modeling of
|
||||
indoor scenarios.
|
||||
|
||||
Vehicular propagation loss models
|
||||
=================================
|
||||
|
||||
The propagation models described in TR 37.885 determines the attenuation caused
|
||||
by path loss and shadowing by considering the propagation environment and the
|
||||
channel condition.
|
||||
|
||||
These models have been implemented by extending the interface
|
||||
:cpp:class:`ThreeGppPropagationLossModel` with the following classes, which
|
||||
are part of the ``propagation`` module:
|
||||
* :cpp:class:`ThreeGppV2vUrbanPropagationLossModel`: implements the models
|
||||
defined in Table 6.2.1-1 of TR 37.885 for the urban scenario.
|
||||
* :cpp:class:`ThreeGppV2vHighwayPropagationLossModel`: implements the models
|
||||
defined in Table 6.2.1-1 of TR 37.885 for the highway scenario.
|
||||
As for all the classes extending the interface :cpp:class:`ThreeGppPropagationLossModel`,
|
||||
they have to be paired with an instance of the class :cpp:class:`ChannelConditionModel`
|
||||
which is used to determine the channel condition.
|
||||
This is done by setting the attribute :cpp:class:`ChannelConditionModel`.
|
||||
To build the channel modeling framework described in TR 37.885,
|
||||
:cpp:class:`ThreeGppV2vUrbanChannelConditionModel` or
|
||||
:cpp:class:`ThreeGppV2vHighwayChannelConditionModel` should be used, but users
|
||||
are allowed to test any other combination.
|
||||
|
||||
.. _sec-3gpp-v2v-ff:
|
||||
|
||||
Vehicular fast fading model
|
||||
===========================
|
||||
|
||||
The fast fading model described in Sec. 6.2.3 of TR 37.885 is based on the one
|
||||
specified in TR 38.901, whose implementation is provided in the ``spectrum`` module
|
||||
(see the :ref:`spectrum module documentation <sec-3gpp-fast-fading-model>`).
|
||||
This model is general and includes different parameters which can
|
||||
be tuned to simulate multiple propagation environments.
|
||||
To better model the channel dynamics in vehicular environments, TR 37.885
|
||||
provides new sets of values for these parameters, specific for
|
||||
vehicle-to-vehicle transmissions in urban and highway scenarios.
|
||||
To select the parameters for vehicular scenarios, it is necessary to set
|
||||
the attribute "Scenario" of the class :cpp:class:`ThreeGppChannelModel` using the value
|
||||
"V2V-Urban" or "V2V-Highway".
|
||||
|
||||
Additionally, TR 37.885 specifies a new equation to compute the Doppler component,
|
||||
which accounts for the mobility of both nodes, as well as scattering
|
||||
from the environment.
|
||||
In particular, the scattering effect is considered by deviating the Doppler
|
||||
frequency by a random value, whose distribution depends on the parameter :math:`v_{scatt}`.
|
||||
TR 37.885 specifies that :math:`v_{scatt}` should be set to the maximum speed of the
|
||||
vehicles in the layout and, if :math:`v_{scatt} = 0`, the scattering effect is not considered.
|
||||
The Doppler equation is implemented in the class :cpp:class:`ThreeGppSpectrumPropagationLossModel`.
|
||||
By means of the attribute "vScatt", it is possible to adjust the value of
|
||||
:math:`v_{scatt} = 0` (by default, the value is set to 0).
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
We implemented the example ``three-gpp-v2v-channel-example.cc`` which shows how to
|
||||
configure the different classes to simulate wireless propagation in vehicular
|
||||
scenarios, it can be found in the folder ``examples/channel-models``.
|
||||
|
||||
We considered two communicating vehicles moving within the scenario, and
|
||||
computed the SNR experienced during the entire simulation, with a time
|
||||
resolution of 10 ms.
|
||||
The vehicles are equipped with 2x2 antenna arrays modeled using the
|
||||
:ref:`3GPP antenna model <sec-3gpp-antenna-model>`.
|
||||
The bearing and the downtilt angles are properly configured and the
|
||||
optimal beamforming vectors are computed at the beginning of the simulation.
|
||||
|
||||
The simulation script accepts the following command line parameters:
|
||||
* *frequency*: the operating frequency in Hz
|
||||
* *txPow*: the transmission power in dBm
|
||||
* *noiseFigure*: the noise figure in dB
|
||||
* *scenario*: the simulation scenario, "V2V-Urban" or "V2V-Highway"
|
||||
|
||||
The "V2V-Urban" scenario simulates urban environment with a rectangular grid of
|
||||
buildings. The vehicles moves with a waypoint mobility model. They start from
|
||||
the same position and travel in the same direction, along the main street.
|
||||
The first vehicle moves at 60 km/h and the second at 30 km/h.
|
||||
At a certain point, the first vehicle turns left while the second continues on
|
||||
the main street.
|
||||
|
||||
The "V2V-Highway" scenario simulates an highway environment in which the
|
||||
two vehicles travel on the same lane, in the same direction, and keep a safety
|
||||
distance of 20 m. They maintain a constant speed of 140 km/h.
|
||||
|
||||
The example generates the output file ``example-output.txt``. Each row of the
|
||||
file is organized as follows:
|
||||
|
||||
``Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState SNR[dB] Pathloss[dB]``
|
||||
|
||||
We also provide the bash script ``three-gpp-v2v-channel-example.sh`` which reads the
|
||||
output file and generates two figures:
|
||||
1. map.gif, a GIF representing the simulation scenario and vehicle mobility;
|
||||
2. snr.png, which represents the behavior of the SNR.
|
||||
|
||||
References
|
||||
**********
|
||||
|
||||
@@ -820,3 +988,9 @@ References
|
||||
in Proc. of the 8th International Symposium on Antennas, Propagation and EM Theory (ISAPE), Kunming, China, Nov 2008.
|
||||
|
||||
.. [38901] 3GPP. 2018. TR 38.901, Study on channel model for frequencies from 0.5 to 100 GHz, V15.0.0. (2018-06).
|
||||
|
||||
.. [37885] 3GPP. 2019. TR 37.885, Study on evaluation methodology of new Vehicle-to-Everything (V2X) use cases for LTE and NR, V15.3.0. (2019-06).
|
||||
|
||||
.. [Boban2016Modeling] M. Boban, X. Gong, and W. Xu, “Modeling the evolution
|
||||
of line-of-sight blockage for V2V channels,” in IEEE 84th Vehicular Technology
|
||||
Conference (VTC-Fall), 2016.
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <cmath>
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/string.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -42,12 +43,18 @@ ChannelCondition::GetTypeId (void)
|
||||
}
|
||||
|
||||
ChannelCondition::ChannelCondition ()
|
||||
: m_losCondition (LosConditionValue::LC_ND),
|
||||
m_o2iCondition (O2iConditionValue::O2I_ND)
|
||||
{}
|
||||
|
||||
ChannelCondition::ChannelCondition (ChannelCondition::LosConditionValue losCondition, ChannelCondition::O2iConditionValue o2iCondition)
|
||||
{
|
||||
m_losCondition = losCondition;
|
||||
m_o2iCondition = o2iCondition;
|
||||
}
|
||||
|
||||
ChannelCondition::~ChannelCondition ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
ChannelCondition::LosConditionValue
|
||||
ChannelCondition::GetLosCondition () const
|
||||
@@ -61,6 +68,78 @@ ChannelCondition::SetLosCondition (LosConditionValue cond)
|
||||
m_losCondition = cond;
|
||||
}
|
||||
|
||||
ChannelCondition::O2iConditionValue
|
||||
ChannelCondition::GetO2iCondition () const
|
||||
{
|
||||
return m_o2iCondition;
|
||||
}
|
||||
|
||||
void
|
||||
ChannelCondition::SetO2iCondition (O2iConditionValue o2iCondition)
|
||||
{
|
||||
m_o2iCondition = o2iCondition;
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelCondition::IsLos () const
|
||||
{
|
||||
return (m_losCondition == ChannelCondition::LOS);
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelCondition::IsNlos () const
|
||||
{
|
||||
return (m_losCondition == ChannelCondition::NLOS);
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelCondition::IsNlosv () const
|
||||
{
|
||||
return (m_losCondition == ChannelCondition::NLOSv);
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelCondition::IsO2i () const
|
||||
{
|
||||
return (m_o2iCondition == ChannelCondition::O2I);
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelCondition::IsO2o () const
|
||||
{
|
||||
return (m_o2iCondition == ChannelCondition::O2O);
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelCondition::IsI2i () const
|
||||
{
|
||||
return (m_o2iCondition == ChannelCondition::I2I);
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelCondition::IsEqual (Ptr<const ChannelCondition> otherCondition) const
|
||||
{
|
||||
return (m_o2iCondition == otherCondition->GetO2iCondition ()
|
||||
&& m_losCondition == otherCondition->GetLosCondition ());
|
||||
}
|
||||
|
||||
std::ostream& operator<< (std::ostream& os, ChannelCondition::LosConditionValue cond)
|
||||
{
|
||||
if (cond == ChannelCondition::LosConditionValue::LOS)
|
||||
{
|
||||
os << "LOS";
|
||||
}
|
||||
else if (cond == ChannelCondition::LosConditionValue::NLOS)
|
||||
{
|
||||
os << "NLOS";
|
||||
}
|
||||
else if (cond == ChannelCondition::LosConditionValue::NLOSv)
|
||||
{
|
||||
os << "NLOSv";
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ChannelConditionModel);
|
||||
@@ -76,12 +155,10 @@ ChannelConditionModel::GetTypeId (void)
|
||||
}
|
||||
|
||||
ChannelConditionModel::ChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
ChannelConditionModel::~ChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
@@ -99,12 +176,10 @@ AlwaysLosChannelConditionModel::GetTypeId (void)
|
||||
}
|
||||
|
||||
AlwaysLosChannelConditionModel::AlwaysLosChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
AlwaysLosChannelConditionModel::~AlwaysLosChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
Ptr<ChannelCondition>
|
||||
AlwaysLosChannelConditionModel::GetChannelCondition (Ptr<const MobilityModel> a,
|
||||
@@ -113,8 +188,7 @@ AlwaysLosChannelConditionModel::GetChannelCondition (Ptr<const MobilityModel> a,
|
||||
NS_UNUSED (a);
|
||||
NS_UNUSED (b);
|
||||
|
||||
Ptr<ChannelCondition> c = CreateObject<ChannelCondition> ();
|
||||
c->SetLosCondition (ChannelCondition::LOS);
|
||||
Ptr<ChannelCondition> c = CreateObject<ChannelCondition> (ChannelCondition::LOS);
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -141,12 +215,10 @@ NeverLosChannelConditionModel::GetTypeId (void)
|
||||
}
|
||||
|
||||
NeverLosChannelConditionModel::NeverLosChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
NeverLosChannelConditionModel::~NeverLosChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
Ptr<ChannelCondition>
|
||||
NeverLosChannelConditionModel::GetChannelCondition (Ptr<const MobilityModel> a,
|
||||
@@ -155,8 +227,7 @@ NeverLosChannelConditionModel::GetChannelCondition (Ptr<const MobilityModel> a,
|
||||
NS_UNUSED (a);
|
||||
NS_UNUSED (b);
|
||||
|
||||
Ptr<ChannelCondition> c = CreateObject<ChannelCondition> ();
|
||||
c->SetLosCondition (ChannelCondition::NLOS);
|
||||
Ptr<ChannelCondition> c = CreateObject<ChannelCondition> (ChannelCondition::NLOS);
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -169,6 +240,43 @@ NeverLosChannelConditionModel::AssignStreams (int64_t stream)
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (NeverLosVehicleChannelConditionModel);
|
||||
|
||||
TypeId
|
||||
NeverLosVehicleChannelConditionModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::NeverLosVehicleChannelConditionModel")
|
||||
.SetParent<ChannelConditionModel> ()
|
||||
.SetGroupName ("Propagation")
|
||||
.AddConstructor<NeverLosVehicleChannelConditionModel> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
NeverLosVehicleChannelConditionModel::NeverLosVehicleChannelConditionModel ()
|
||||
{}
|
||||
|
||||
NeverLosVehicleChannelConditionModel::~NeverLosVehicleChannelConditionModel ()
|
||||
{}
|
||||
|
||||
Ptr<ChannelCondition>
|
||||
NeverLosVehicleChannelConditionModel::GetChannelCondition (Ptr<const MobilityModel> /* a */,
|
||||
Ptr<const MobilityModel> /* b */) const
|
||||
{
|
||||
|
||||
Ptr<ChannelCondition> c = CreateObject<ChannelCondition> (ChannelCondition::NLOSv);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int64_t
|
||||
NeverLosVehicleChannelConditionModel::AssignStreams (int64_t /* stream */)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ThreeGppChannelConditionModel);
|
||||
|
||||
TypeId
|
||||
@@ -194,8 +302,7 @@ ThreeGppChannelConditionModel::ThreeGppChannelConditionModel ()
|
||||
}
|
||||
|
||||
ThreeGppChannelConditionModel::~ThreeGppChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void ThreeGppChannelConditionModel::DoDispose ()
|
||||
{
|
||||
@@ -239,38 +346,63 @@ ThreeGppChannelConditionModel::GetChannelCondition (Ptr<const MobilityModel> a,
|
||||
// generate a new channel condition
|
||||
if (notFound || update)
|
||||
{
|
||||
// compute the LOS probability (see 3GPP TR 38.901, Sec. 7.4.2)
|
||||
double pLos = ComputePlos (a, b);
|
||||
|
||||
// draw a random value
|
||||
double pRef = m_uniformVar->GetValue ();
|
||||
|
||||
// get the channel condition
|
||||
cond = CreateObject<ChannelCondition> ();
|
||||
if (pRef <= pLos)
|
||||
{
|
||||
// LOS
|
||||
cond->SetLosCondition (ChannelCondition::LosConditionValue::LOS);
|
||||
}
|
||||
else
|
||||
{
|
||||
// NLOS
|
||||
cond->SetLosCondition (ChannelCondition::LosConditionValue::NLOS);
|
||||
}
|
||||
|
||||
{
|
||||
// store the channel condition in m_channelConditionMap, used as cache.
|
||||
// For this reason you see a const_cast.
|
||||
Item mapItem;
|
||||
mapItem.m_condition = cond;
|
||||
mapItem.m_generatedTime = Simulator::Now ();
|
||||
const_cast<ThreeGppChannelConditionModel*> (this)->m_channelConditionMap [key] = mapItem;
|
||||
}
|
||||
cond = ComputeChannelCondition (a, b);
|
||||
// store the channel condition in m_channelConditionMap, used as cache.
|
||||
// For this reason you see a const_cast.
|
||||
Item mapItem;
|
||||
mapItem.m_condition = cond;
|
||||
mapItem.m_generatedTime = Simulator::Now ();
|
||||
const_cast<ThreeGppChannelConditionModel*> (this)->m_channelConditionMap [key] = mapItem;
|
||||
}
|
||||
|
||||
return cond;
|
||||
}
|
||||
|
||||
Ptr<ChannelCondition>
|
||||
ThreeGppChannelConditionModel::ComputeChannelCondition (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << a << b);
|
||||
Ptr<ChannelCondition> cond = CreateObject<ChannelCondition> ();
|
||||
|
||||
// compute the LOS probability
|
||||
double pLos = ComputePlos (a, b);
|
||||
double pNlos = ComputePnlos (a, b);
|
||||
|
||||
// draw a random value
|
||||
double pRef = m_uniformVar->GetValue ();
|
||||
|
||||
NS_LOG_DEBUG ("pRef " << pRef << " pLos " << pLos << " pNlos " << pNlos);
|
||||
|
||||
// get the channel condition
|
||||
if (pRef <= pLos)
|
||||
{
|
||||
// LOS
|
||||
cond->SetLosCondition (ChannelCondition::LosConditionValue::LOS);
|
||||
}
|
||||
else if (pRef <= pLos + pNlos)
|
||||
{
|
||||
// NLOS
|
||||
cond->SetLosCondition (ChannelCondition::LosConditionValue::NLOS);
|
||||
}
|
||||
else
|
||||
{
|
||||
// NLOSv (added to support vehicular scenarios)
|
||||
cond->SetLosCondition (ChannelCondition::LosConditionValue::NLOSv);
|
||||
}
|
||||
|
||||
return cond;
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppChannelConditionModel::ComputePnlos (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << a << b);
|
||||
// by default returns 1 - PLOS
|
||||
return (1 - ComputePlos (a, b));
|
||||
}
|
||||
|
||||
int64_t
|
||||
ThreeGppChannelConditionModel::AssignStreams (int64_t stream)
|
||||
{
|
||||
@@ -319,12 +451,10 @@ ThreeGppRmaChannelConditionModel::GetTypeId (void)
|
||||
|
||||
ThreeGppRmaChannelConditionModel::ThreeGppRmaChannelConditionModel ()
|
||||
: ThreeGppChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
ThreeGppRmaChannelConditionModel::~ThreeGppRmaChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
double
|
||||
ThreeGppRmaChannelConditionModel::ComputePlos (Ptr<const MobilityModel> a,
|
||||
@@ -367,12 +497,10 @@ ThreeGppUmaChannelConditionModel::GetTypeId (void)
|
||||
|
||||
ThreeGppUmaChannelConditionModel::ThreeGppUmaChannelConditionModel ()
|
||||
: ThreeGppChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
ThreeGppUmaChannelConditionModel::~ThreeGppUmaChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
double
|
||||
ThreeGppUmaChannelConditionModel::ComputePlos (Ptr<const MobilityModel> a,
|
||||
@@ -437,12 +565,10 @@ ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId (void)
|
||||
|
||||
ThreeGppUmiStreetCanyonChannelConditionModel::ThreeGppUmiStreetCanyonChannelConditionModel ()
|
||||
: ThreeGppChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
ThreeGppUmiStreetCanyonChannelConditionModel::~ThreeGppUmiStreetCanyonChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
double
|
||||
ThreeGppUmiStreetCanyonChannelConditionModel::ComputePlos (Ptr<const MobilityModel> a,
|
||||
@@ -492,12 +618,10 @@ ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId (void)
|
||||
|
||||
ThreeGppIndoorMixedOfficeChannelConditionModel::ThreeGppIndoorMixedOfficeChannelConditionModel ()
|
||||
: ThreeGppChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
ThreeGppIndoorMixedOfficeChannelConditionModel::~ThreeGppIndoorMixedOfficeChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
double
|
||||
ThreeGppIndoorMixedOfficeChannelConditionModel::ComputePlos (Ptr<const MobilityModel> a,
|
||||
@@ -551,12 +675,10 @@ ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId (void)
|
||||
|
||||
ThreeGppIndoorOpenOfficeChannelConditionModel::ThreeGppIndoorOpenOfficeChannelConditionModel ()
|
||||
: ThreeGppChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
ThreeGppIndoorOpenOfficeChannelConditionModel::~ThreeGppIndoorOpenOfficeChannelConditionModel ()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
double
|
||||
ThreeGppIndoorOpenOfficeChannelConditionModel::ComputePlos (Ptr<const MobilityModel> a,
|
||||
|
||||
@@ -48,7 +48,20 @@ public:
|
||||
enum LosConditionValue
|
||||
{
|
||||
LOS, //!< Line of Sight
|
||||
NLOS //!< Non Line of Sight
|
||||
NLOS, //!< Non Line of Sight
|
||||
NLOSv, //!< Non Line of Sight due to a vehicle
|
||||
LC_ND //!< Los condition not defined
|
||||
};
|
||||
|
||||
/**
|
||||
* Possible values for Outdoor to Indoor condition.
|
||||
*/
|
||||
enum O2iConditionValue
|
||||
{
|
||||
O2O, //!< Outdoor to Outdoor
|
||||
O2I, //!< Outdoor to Indoor
|
||||
I2I, //!< Indoor to Indoor
|
||||
O2I_ND //!< Outdoor to Indoor condition not defined
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -62,6 +75,13 @@ public:
|
||||
* Constructor for the ChannelCondition class
|
||||
*/
|
||||
ChannelCondition ();
|
||||
|
||||
/**
|
||||
* Constructor for the ChannelCondition class
|
||||
* \param losCondition the LOS condition value
|
||||
* \param o2iCondition the O2I condition value (by default is set to O2O)
|
||||
*/
|
||||
ChannelCondition (LosConditionValue losCondition, O2iConditionValue o2iCondition = O2O);
|
||||
|
||||
/**
|
||||
* Destructor for the ChannelCondition class
|
||||
@@ -83,9 +103,89 @@ public:
|
||||
* \param the LosConditionValue
|
||||
*/
|
||||
void SetLosCondition (LosConditionValue losCondition);
|
||||
|
||||
/**
|
||||
* Get the O2iConditionValue contaning the information about the O2I
|
||||
* state of the channel
|
||||
*
|
||||
* \return the O2iConditionValue
|
||||
*/
|
||||
O2iConditionValue GetO2iCondition () const;
|
||||
|
||||
/**
|
||||
* Set the O2iConditionValue contaning the information about the O2I
|
||||
* state of the channel
|
||||
*
|
||||
* \param o2iCondition the O2iConditionValue
|
||||
*/
|
||||
void SetO2iCondition (O2iConditionValue o2iCondition);
|
||||
|
||||
/**
|
||||
* Return true if the channel condition is LOS
|
||||
*
|
||||
* \return true if the channel condition is LOS
|
||||
*/
|
||||
bool IsLos () const;
|
||||
|
||||
/**
|
||||
* Return true if the channel condition is NLOS
|
||||
*
|
||||
* It does not consider the case in which the LOS path is obstructed by a
|
||||
* vehicle. This case is represented as a separate channel condition (NLOSv),
|
||||
* use the method IsNlosv instead.
|
||||
*
|
||||
* \return true if the channel condition is NLOS
|
||||
*/
|
||||
bool IsNlos () const;
|
||||
|
||||
/**
|
||||
* Return true if the channel condition is NLOSv
|
||||
*
|
||||
* \return true if the channel condition is NLOSv
|
||||
*/
|
||||
bool IsNlosv () const;
|
||||
|
||||
/**
|
||||
* Return true if the channel is outdoor-to-indoor
|
||||
*
|
||||
* \return true if the channel is outdoor-to-indoor
|
||||
*/
|
||||
bool IsO2i () const;
|
||||
|
||||
/**
|
||||
* Return true if the channel is outdoor-to-outdoor
|
||||
*
|
||||
* \return true if the channel is outdoor-to-outdoor
|
||||
*/
|
||||
bool IsO2o () const;
|
||||
|
||||
/**
|
||||
* Return true if the channel is indoor-to-indoor
|
||||
*
|
||||
* \return true if the channel is indoor-to-indoor
|
||||
*/
|
||||
bool IsI2i () const;
|
||||
|
||||
/**
|
||||
* Return true if this instance is equivalent to the one passed as argument
|
||||
*
|
||||
* \param otherCondition the other instance to compare with this instance
|
||||
* \return true if this instance is equivalent to the one passed as argument
|
||||
*/
|
||||
bool IsEqual (Ptr<const ChannelCondition> otherCondition) const;
|
||||
|
||||
private:
|
||||
LosConditionValue m_losCondition; //!< contains the information about the LOS/NLOS state of the channel
|
||||
LosConditionValue m_losCondition; //!< contains the information about the LOS state of the channel
|
||||
O2iConditionValue m_o2iCondition; //!< contains the information about the O2I state of the channel
|
||||
|
||||
/**
|
||||
* Prints a LosConditionValue to output
|
||||
* \param os the output stream
|
||||
* \param cond the LosConditionValue
|
||||
*
|
||||
* \return a reference to the output stream
|
||||
*/
|
||||
friend std::ostream& operator<< (std::ostream& os, LosConditionValue cond);
|
||||
|
||||
};
|
||||
|
||||
@@ -133,7 +233,7 @@ public:
|
||||
* 'stream'. Return the number of streams (possibly zero) that
|
||||
* have been assigned.
|
||||
*
|
||||
* \param stream
|
||||
* \param stream the offset used to set the stream numbers
|
||||
* \return the number of stream indices assigned by this model
|
||||
*/
|
||||
virtual int64_t AssignStreams (int64_t stream) = 0;
|
||||
@@ -170,12 +270,12 @@ public:
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* Constructor for the ChannelConditionModel class
|
||||
* Constructor
|
||||
*/
|
||||
AlwaysLosChannelConditionModel ();
|
||||
|
||||
/**
|
||||
* Destructor for the ChannelConditionModel class
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~AlwaysLosChannelConditionModel ();
|
||||
|
||||
@@ -199,7 +299,7 @@ public:
|
||||
* \brief Copy constructor
|
||||
*
|
||||
* Defined and unimplemented to avoid misuse
|
||||
* \returns
|
||||
* \returns a copy of the object
|
||||
*/
|
||||
AlwaysLosChannelConditionModel &operator = (const AlwaysLosChannelConditionModel &) = delete;
|
||||
|
||||
@@ -209,7 +309,7 @@ public:
|
||||
* 'stream'. Return the number of streams (possibly zero) that
|
||||
* have been assigned.
|
||||
*
|
||||
* \param stream
|
||||
* \param stream the offset used to set the stream numbers
|
||||
* \return the number of stream indices assigned by this model
|
||||
*/
|
||||
virtual int64_t AssignStreams (int64_t stream) override;
|
||||
@@ -231,12 +331,12 @@ public:
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* Constructor for the ChannelConditionModel class
|
||||
* Constructor
|
||||
*/
|
||||
NeverLosChannelConditionModel ();
|
||||
|
||||
/**
|
||||
* Destructor for the ChannelConditionModel class
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~NeverLosChannelConditionModel ();
|
||||
|
||||
@@ -260,7 +360,7 @@ public:
|
||||
* \brief Copy constructor
|
||||
*
|
||||
* Defined and unimplemented to avoid misuse
|
||||
* \returns
|
||||
* \returns a copy of the object
|
||||
*/
|
||||
NeverLosChannelConditionModel &operator = (const NeverLosChannelConditionModel &) = delete;
|
||||
|
||||
@@ -270,7 +370,68 @@ public:
|
||||
* 'stream'. Return the number of streams (possibly zero) that
|
||||
* have been assigned.
|
||||
*
|
||||
* \param stream
|
||||
* \param stream the offset used to set the stream numbers
|
||||
* \return the number of stream indices assigned by this model
|
||||
*/
|
||||
virtual int64_t AssignStreams (int64_t stream) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup propagation
|
||||
*
|
||||
* \brief Models a never in-LoS condition model caused by a blocking vehicle
|
||||
*/
|
||||
class NeverLosVehicleChannelConditionModel : public ChannelConditionModel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Get the type ID.
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
NeverLosVehicleChannelConditionModel ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~NeverLosVehicleChannelConditionModel ();
|
||||
|
||||
/**
|
||||
* Computes the condition of the channel between a and b, that will be always NLOSv
|
||||
*
|
||||
* \param a mobility model
|
||||
* \param b mobility model
|
||||
* \return the condition of the channel between a and b, that will be always NLOSv
|
||||
*/
|
||||
virtual Ptr<ChannelCondition> GetChannelCondition (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const override;
|
||||
|
||||
/**
|
||||
* \brief Copy constructor
|
||||
*
|
||||
* Defined and unimplemented to avoid misuse
|
||||
*/
|
||||
NeverLosVehicleChannelConditionModel (const NeverLosVehicleChannelConditionModel&) = delete;
|
||||
|
||||
/**
|
||||
* \brief Copy constructor
|
||||
*
|
||||
* Defined and unimplemented to avoid misuse
|
||||
* \returns a copy of the object
|
||||
*/
|
||||
NeverLosVehicleChannelConditionModel &operator = (const NeverLosVehicleChannelConditionModel &) = delete;
|
||||
|
||||
/**
|
||||
* If this model uses objects of type RandomVariableStream,
|
||||
* set the stream numbers to the integers starting with the offset
|
||||
* 'stream'. Return the number of streams (possibly zero) that
|
||||
* have been assigned.
|
||||
*
|
||||
* \param stream the offset used to set the stream numbers
|
||||
* \return the number of stream indices assigned by this model
|
||||
*/
|
||||
virtual int64_t AssignStreams (int64_t stream) override;
|
||||
@@ -305,9 +466,9 @@ public:
|
||||
/**
|
||||
* \brief Retrieve the condition of the channel between a and b.
|
||||
*
|
||||
* If the channel condition does not exists, the method creates it and
|
||||
* store it in a local cache, that will be updated following the "UpdatePeriod"
|
||||
* parameter.
|
||||
* If the channel condition does not exists, the method computes it by calling
|
||||
* ComputeChannelCondition and stores it in a local cache, that will be updated
|
||||
* following the "UpdatePeriod" parameter.
|
||||
*
|
||||
* \param a mobility model
|
||||
* \param b mobility model
|
||||
@@ -321,7 +482,7 @@ public:
|
||||
* 'stream'. Return the number of streams (possibly zero) that
|
||||
* have been assigned.
|
||||
*
|
||||
* \param stream
|
||||
* \param stream the offset used to set the stream numbers
|
||||
* \return the number of stream indices assigned by this model
|
||||
*/
|
||||
virtual int64_t AssignStreams (int64_t stream) override;
|
||||
@@ -329,6 +490,17 @@ public:
|
||||
protected:
|
||||
virtual void DoDispose () override;
|
||||
|
||||
/**
|
||||
* Determine the density of vehicles in a V2V scenario.
|
||||
*/
|
||||
enum VehicleDensity
|
||||
{
|
||||
LOW,
|
||||
MEDIUM,
|
||||
HIGH,
|
||||
INVALID
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Computes the 2D distance between two 3D vectors
|
||||
* \param a the first 3D vector
|
||||
@@ -336,16 +508,37 @@ protected:
|
||||
* \return the 2D distance between a and b
|
||||
*/
|
||||
static double Calculate2dDistance (const Vector &a, const Vector &b);
|
||||
|
||||
Ptr<UniformRandomVariable> m_uniformVar; //!< uniform random variable
|
||||
|
||||
private:
|
||||
/**
|
||||
* Compute the LOS probability as specified in Table 7.4.2-1 of 3GPP TR 38.901.
|
||||
* This method computes the channel condition based on a probabilistic model
|
||||
* that is specific for the scenario of interest
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the channel condition
|
||||
*/
|
||||
Ptr<ChannelCondition> ComputeChannelCondition (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const;
|
||||
|
||||
/**
|
||||
* Compute the LOS probability.
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the LOS probability
|
||||
*/
|
||||
virtual double ComputePlos (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const = 0;
|
||||
|
||||
/**
|
||||
* Compute the NLOS probability. By default returns 1 - PLOS
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the LOS probability
|
||||
*/
|
||||
virtual double ComputePnlos (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const;
|
||||
|
||||
/**
|
||||
* \brief Returns a unique and reciprocal key for the channel between a and b.
|
||||
@@ -366,7 +559,6 @@ private:
|
||||
|
||||
std::unordered_map<uint32_t, Item> m_channelConditionMap; //!< map to store the channel conditions
|
||||
Time m_updatePeriod; //!< the update period for the channel condition
|
||||
Ptr<UniformRandomVariable> m_uniformVar; //!< uniform random variable
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 SIGNET Lab, Department of Information Engineering,
|
||||
* University of Padova
|
||||
*
|
||||
* 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 "probabilistic-v2v-channel-condition-model.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/mobility-model.h"
|
||||
#include "ns3/enum.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ProbabilisticV2vChannelConditionModel");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ProbabilisticV2vUrbanChannelConditionModel);
|
||||
|
||||
TypeId
|
||||
ProbabilisticV2vUrbanChannelConditionModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::ProbabilisticV2vUrbanChannelConditionModel")
|
||||
.SetParent<ThreeGppChannelConditionModel> ()
|
||||
.SetGroupName ("Propagation")
|
||||
.AddConstructor<ProbabilisticV2vUrbanChannelConditionModel> ()
|
||||
.AddAttribute ("Density", "Specifies the density of the vehicles in the scenario."
|
||||
"It can be set to Low, Medium or High.",
|
||||
EnumValue (VehicleDensity::LOW),
|
||||
MakeEnumAccessor (&ProbabilisticV2vUrbanChannelConditionModel::m_densityUrban),
|
||||
MakeEnumChecker (VehicleDensity::LOW, "Low",
|
||||
VehicleDensity::MEDIUM, "Medium",
|
||||
VehicleDensity::HIGH, "High"))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
ProbabilisticV2vUrbanChannelConditionModel::ProbabilisticV2vUrbanChannelConditionModel ()
|
||||
: ThreeGppChannelConditionModel ()
|
||||
{}
|
||||
|
||||
ProbabilisticV2vUrbanChannelConditionModel::~ProbabilisticV2vUrbanChannelConditionModel ()
|
||||
{}
|
||||
|
||||
double
|
||||
ProbabilisticV2vUrbanChannelConditionModel::ComputePlos (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
// compute the 2D distance between a and b
|
||||
double distance2D = Calculate2dDistance (a->GetPosition (), b->GetPosition ());
|
||||
|
||||
double pLos = 0.0;
|
||||
switch (m_densityUrban)
|
||||
{
|
||||
case VehicleDensity::LOW:
|
||||
pLos = std::min (1.0, std::max (0.0, 0.8548 * exp (-0.0064 * distance2D)));
|
||||
break;
|
||||
case VehicleDensity::MEDIUM:
|
||||
pLos = std::min (1.0, std::max (0.0, 0.8372 * exp (-0.0114 * distance2D)));
|
||||
break;
|
||||
case VehicleDensity::HIGH:
|
||||
pLos = std::min (1.0, std::max (0.0, 0.8962 * exp (-0.017 * distance2D)));
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Undefined density, choose between Low, Medium and High");
|
||||
}
|
||||
|
||||
return pLos;
|
||||
}
|
||||
|
||||
double
|
||||
ProbabilisticV2vUrbanChannelConditionModel::ComputePnlos (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
// compute the 2D distance between a and b
|
||||
double distance2D = Calculate2dDistance (a->GetPosition (), b->GetPosition ());
|
||||
|
||||
// compute the NLOSv probability
|
||||
double pNlosv = 0.0;
|
||||
switch (m_densityUrban)
|
||||
{
|
||||
case VehicleDensity::LOW:
|
||||
pNlosv = std::min (1.0, std::max (0.0, 1 / (0.0396 * distance2D) * exp (-(log (distance2D) - 5.2718) * (log (distance2D) - 5.2718) / 3.4827)));
|
||||
break;
|
||||
case VehicleDensity::MEDIUM:
|
||||
pNlosv = std::min (1.0, std::max (0.0, 1 / (0.0312 * distance2D) * exp (-(log (distance2D) - 5.0063) * (log (distance2D) - 5.0063) / 2.4544)));
|
||||
break;
|
||||
case VehicleDensity::HIGH:
|
||||
pNlosv = std::min (1.0, std::max (0.0, 1 / (0.0242 * distance2D) * exp (-(log (distance2D) - 5.0115) * (log (distance2D) - 5.0115) / 2.2092)));
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Undefined density, choose between Low, Medium and High");
|
||||
}
|
||||
|
||||
// derive the NLOS probability
|
||||
double pNlos = 1 - ComputePlos (a, b) - pNlosv;
|
||||
return pNlos;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ProbabilisticV2vHighwayChannelConditionModel);
|
||||
|
||||
TypeId
|
||||
ProbabilisticV2vHighwayChannelConditionModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::ProbabilisticV2vHighwayChannelConditionModel")
|
||||
.SetParent<ThreeGppChannelConditionModel> ()
|
||||
.SetGroupName ("Propagation")
|
||||
.AddConstructor<ProbabilisticV2vHighwayChannelConditionModel> ()
|
||||
.AddAttribute ("Density", "Specifies the density of the vehicles in the scenario."
|
||||
"It can be set to Low, Medium or High.",
|
||||
EnumValue (VehicleDensity::LOW),
|
||||
MakeEnumAccessor (&ProbabilisticV2vHighwayChannelConditionModel::m_densityHighway),
|
||||
MakeEnumChecker (VehicleDensity::LOW, "Low",
|
||||
VehicleDensity::MEDIUM, "Medium",
|
||||
VehicleDensity::HIGH, "High"))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
ProbabilisticV2vHighwayChannelConditionModel::ProbabilisticV2vHighwayChannelConditionModel ()
|
||||
: ThreeGppChannelConditionModel ()
|
||||
{}
|
||||
|
||||
ProbabilisticV2vHighwayChannelConditionModel::~ProbabilisticV2vHighwayChannelConditionModel ()
|
||||
{}
|
||||
|
||||
double
|
||||
ProbabilisticV2vHighwayChannelConditionModel::ComputePlos (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
// compute the 2D distance between a and b
|
||||
double distance2D = Calculate2dDistance (a->GetPosition (), b->GetPosition ());
|
||||
|
||||
double aLos = 0.0;
|
||||
double bLos = 0.0;
|
||||
double cLos = 0.0;
|
||||
switch (m_densityHighway)
|
||||
{
|
||||
case VehicleDensity::LOW:
|
||||
aLos = 1.5e-6;
|
||||
bLos = -0.0015;
|
||||
cLos = 1.0;
|
||||
break;
|
||||
case VehicleDensity::MEDIUM:
|
||||
aLos = 2.7e-6;
|
||||
bLos = -0.0025;
|
||||
cLos = 1.0;
|
||||
break;
|
||||
case VehicleDensity::HIGH:
|
||||
aLos = 3.2e-6;
|
||||
bLos = -0.003;
|
||||
cLos = 1.0;
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Undefined density, choose between Low, Medium and High");
|
||||
}
|
||||
|
||||
double pLos = std::min (1.0, std::max (0.0, aLos * distance2D * distance2D + bLos * distance2D + cLos));
|
||||
|
||||
return pLos;
|
||||
}
|
||||
|
||||
double
|
||||
ProbabilisticV2vHighwayChannelConditionModel::ComputePnlos (Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
// compute the 2D distance between a and b
|
||||
double distance2D = Calculate2dDistance (a->GetPosition (), b->GetPosition ());
|
||||
|
||||
double aNlos = 0.0;
|
||||
double bNlos = 0.0;
|
||||
double cNlos = 0.0;
|
||||
switch (m_densityHighway)
|
||||
{
|
||||
case VehicleDensity::LOW:
|
||||
aNlos = -2.9e-7;
|
||||
bNlos = 0.00059;
|
||||
cNlos = 0.0017;
|
||||
break;
|
||||
case VehicleDensity::MEDIUM:
|
||||
aNlos = -3.7e-7;
|
||||
bNlos = 0.00061;
|
||||
cNlos = 0.015;
|
||||
break;
|
||||
case VehicleDensity::HIGH:
|
||||
aNlos = -4.1e-7;
|
||||
bNlos = 0.00067;
|
||||
cNlos = 0.0;
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Undefined density, choose between Low, Medium and High");
|
||||
}
|
||||
|
||||
double pNlos = std::min (1.0, std::max (0.0, aNlos * pow (distance2D, 2) + bNlos * distance2D + cNlos));
|
||||
|
||||
return pNlos;
|
||||
}
|
||||
|
||||
} // end namespace ns3
|
||||
@@ -0,0 +1,135 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 SIGNET Lab, Department of Information Engineering,
|
||||
* University of Padova
|
||||
*
|
||||
* 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 PROBABILISTIC_V2V_CHANNEL_CONDITION_MODEL_H
|
||||
#define PROBABILISTIC_V2V_CHANNEL_CONDITION_MODEL_H
|
||||
|
||||
#include "ns3/channel-condition-model.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class MobilityModel;
|
||||
|
||||
/**
|
||||
* \ingroup propagation
|
||||
*
|
||||
* \brief Computes the channel condition for the V2V Urban scenario
|
||||
*
|
||||
* Computes the channel condition following the probabilistic model described in
|
||||
* M. Boban, X.Gong, and W. Xu, “Modeling the evolution of line-of-sight
|
||||
* blockage for V2V channels,” in IEEE 84th Vehicular Technology
|
||||
* Conference (VTC-Fall), 2016.
|
||||
*/
|
||||
class ProbabilisticV2vUrbanChannelConditionModel : public ThreeGppChannelConditionModel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Get the type ID.
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* Constructor for the ProbabilisticV2vUrbanChannelConditionModel class
|
||||
*/
|
||||
ProbabilisticV2vUrbanChannelConditionModel ();
|
||||
|
||||
/**
|
||||
* Destructor for the ProbabilisticV2vUrbanChannelConditionModel class
|
||||
*/
|
||||
virtual ~ProbabilisticV2vUrbanChannelConditionModel () override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Compute the LOS probability
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the LOS probability
|
||||
*/
|
||||
virtual double ComputePlos (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const override;
|
||||
|
||||
/**
|
||||
* Compute the NLOS probability
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the NLOS probability
|
||||
*/
|
||||
virtual double ComputePnlos (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const override;
|
||||
|
||||
enum VehicleDensity m_densityUrban {VehicleDensity::INVALID}; //!< vehicle density
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup propagation
|
||||
*
|
||||
* \brief Computes the channel condition for the V2V Highway scenario
|
||||
*
|
||||
* Computes the channel condition following the probabilistic model described in
|
||||
* M. Boban, X.Gong, and W. Xu, “Modeling the evolution of line-of-sight
|
||||
* blockage for V2V channels,” in IEEE 84th Vehicular Technology
|
||||
* Conference (VTC-Fall), 2016.
|
||||
*/
|
||||
class ProbabilisticV2vHighwayChannelConditionModel : public ThreeGppChannelConditionModel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Get the type ID.
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* Constructor for the ProbabilisticV2vHighwayChannelConditionModel class
|
||||
*/
|
||||
ProbabilisticV2vHighwayChannelConditionModel ();
|
||||
|
||||
/**
|
||||
* Destructor for the ProbabilisticV2vHighwayChannelConditionModel class
|
||||
*/
|
||||
virtual ~ProbabilisticV2vHighwayChannelConditionModel () override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Compute the LOS probability
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the LOS probability
|
||||
*/
|
||||
virtual double ComputePlos (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const override;
|
||||
|
||||
/**
|
||||
* Compute the NLOS probability
|
||||
*
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \return the NLOS probability
|
||||
*/
|
||||
virtual double ComputePnlos (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b) const override;
|
||||
|
||||
enum VehicleDensity m_densityHighway {VehicleDensity::INVALID}; //!< vehicle density
|
||||
};
|
||||
|
||||
} // end ns3 namespace
|
||||
|
||||
#endif /* PROBABILISTIC_V2V_CHANNEL_CONDITION_MODEL_H */
|
||||
@@ -139,21 +139,8 @@ ThreeGppPropagationLossModel::DoCalcRxPower (double txPowerDbm,
|
||||
std::pair<double, double> heights = GetUtAndBsHeights (a->GetPosition ().z, b->GetPosition ().z);
|
||||
|
||||
double rxPow = txPowerDbm;
|
||||
if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::LOS)
|
||||
{
|
||||
rxPow -= GetLossLos (distance2d, distance3d, heights.first, heights.second);
|
||||
NS_LOG_DEBUG ("Channel codition is LOS, rxPower = " << rxPow);
|
||||
}
|
||||
else if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::NLOS)
|
||||
{
|
||||
rxPow -= GetLossNlos (distance2d, distance3d, heights.first, heights.second);
|
||||
NS_LOG_DEBUG ("Channel codition is NLOS, rxPower = " << rxPow);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Unknown channel condition");
|
||||
}
|
||||
|
||||
rxPow -= GetLoss (cond, distance2d, distance3d, heights.first, heights.second);
|
||||
|
||||
if (m_shadowingEnabled)
|
||||
{
|
||||
rxPow -= GetShadowing (a, b, cond->GetLosCondition ());
|
||||
@@ -162,6 +149,39 @@ ThreeGppPropagationLossModel::DoCalcRxPower (double txPowerDbm,
|
||||
return rxPow;
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppPropagationLossModel::GetLoss (Ptr<ChannelCondition> cond, double distance2d, double distance3d, double hUt, double hBs) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
double loss = 0;
|
||||
if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::LOS)
|
||||
{
|
||||
loss = GetLossLos (distance2d, distance3d, hUt, hBs);
|
||||
}
|
||||
else if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::NLOSv)
|
||||
{
|
||||
loss = GetLossNlosv (distance2d, distance3d, hUt, hBs);
|
||||
}
|
||||
else if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::NLOS)
|
||||
{
|
||||
loss = GetLossNlos (distance2d, distance3d, hUt, hBs);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Unknown channel condition");
|
||||
}
|
||||
return loss;
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppPropagationLossModel::GetLossNlosv (double distance2D, double distance3D, double hUt, double hBs) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_FATAL_ERROR ("Unsupported channel condition (NLOSv)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppPropagationLossModel::GetShadowing (Ptr<MobilityModel> a, Ptr<MobilityModel> b, ChannelCondition::LosConditionValue cond) const
|
||||
{
|
||||
|
||||
@@ -111,6 +111,17 @@ private:
|
||||
* \return the number of stream indices assigned by this model
|
||||
*/
|
||||
virtual int64_t DoAssignStreams (int64_t stream) override;
|
||||
|
||||
/**
|
||||
* \brief Computes the pathloss between a and b
|
||||
* \param cond the channel condition
|
||||
* \param distance2D the 2D distance between tx and rx in meters
|
||||
* \param distance3D the 3D distance between tx and rx in meters
|
||||
* \param hUt the height of the UT in meters
|
||||
* \param hBs the height of the BS in meters
|
||||
* \return pathloss value in dB
|
||||
*/
|
||||
double GetLoss (Ptr<ChannelCondition> cond, double distance2D, double distance3D, double hUt, double hBs) const;
|
||||
|
||||
/**
|
||||
* \brief Computes the pathloss between a and b considering that the line of
|
||||
@@ -133,6 +144,18 @@ private:
|
||||
* \return pathloss value in dB
|
||||
*/
|
||||
virtual double GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const = 0;
|
||||
|
||||
/**
|
||||
* \brief Computes the pathloss between a and b considering that the line of
|
||||
* sight is obstructed by a vehicle. By default it raises an error to
|
||||
* avoid misuse.
|
||||
* \param distance2D the 2D distance between tx and rx in meters
|
||||
* \param distance3D the 3D distance between tx and rx in meters
|
||||
* \param hUt the height of the UT in meters
|
||||
* \param hBs the height of the BS in meters
|
||||
* \return pathloss value in dB
|
||||
*/
|
||||
virtual double GetLossNlosv (double distance2D, double distance3D, double hUt, double hBs) const;
|
||||
|
||||
/**
|
||||
* \brief Determines hUT and hBS. The default implementation assumes that
|
||||
|
||||
235
src/propagation/model/three-gpp-v2v-propagation-loss-model.cc
Normal file
235
src/propagation/model/three-gpp-v2v-propagation-loss-model.cc
Normal file
@@ -0,0 +1,235 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 SIGNET Lab, Department of Information Engineering,
|
||||
* University of Padova
|
||||
*
|
||||
* 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 "three-gpp-v2v-propagation-loss-model.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/string.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ThreeGppV2vPropagationLossModel");
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ThreeGppV2vUrbanPropagationLossModel);
|
||||
|
||||
TypeId
|
||||
ThreeGppV2vUrbanPropagationLossModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::ThreeGppV2vUrbanPropagationLossModel")
|
||||
.SetParent<ThreeGppPropagationLossModel> ()
|
||||
.SetGroupName ("Propagation")
|
||||
.AddConstructor<ThreeGppV2vUrbanPropagationLossModel> ()
|
||||
.AddAttribute ("PercType3Vehicles",
|
||||
"The percentage of vehicles of type 3 (i.e., trucks) in the scenario",
|
||||
DoubleValue (0.0),
|
||||
MakeDoubleAccessor (&ThreeGppV2vUrbanPropagationLossModel::m_percType3Vehicles),
|
||||
MakeDoubleChecker<double> (0.0, 100.0))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
ThreeGppV2vUrbanPropagationLossModel::ThreeGppV2vUrbanPropagationLossModel ()
|
||||
: ThreeGppPropagationLossModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_uniformVar = CreateObject<UniformRandomVariable> ();
|
||||
m_logNorVar = CreateObject<LogNormalRandomVariable> ();
|
||||
|
||||
// set a default channel condition model
|
||||
// TODO the default ccm needs buildings, how to do this?
|
||||
// m_channelConditionModel = CreateObject<ThreeGppRmaChannelConditionModel> ();
|
||||
}
|
||||
|
||||
ThreeGppV2vUrbanPropagationLossModel::~ThreeGppV2vUrbanPropagationLossModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppV2vUrbanPropagationLossModel::GetLossLos (double /* distance2D */, double distance3D, double /* hUt */, double /* hBs */) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// compute the pathloss (see 3GPP TR 37.885, Table 6.2.1-1)
|
||||
double loss = 38.77 + 16.7 * log10 (distance3D) + 18.2 * log10 (m_frequency / 1e9);
|
||||
|
||||
return loss;
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppV2vUrbanPropagationLossModel::GetLossNlosv (double distance2D, double distance3D, double hUt, double hBs) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// compute the pathloss (see 3GPP TR 37.885, Table 6.2.1-1)
|
||||
double loss = GetLossLos (distance2D, distance3D, hUt, hBs) + GetAdditionalNlosvLoss (distance3D, hUt, hBs);
|
||||
|
||||
return loss;
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppV2vUrbanPropagationLossModel::GetAdditionalNlosvLoss (double distance3D, double hUt, double hBs) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
// 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 (hUt, hBs) > blockerHeight)
|
||||
{
|
||||
// Case 1: Minimum antenna height value of TX and RX > Blocker height
|
||||
additionalLoss = 0;
|
||||
}
|
||||
else if (std::max (hUt, hBs) < 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;
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppV2vUrbanPropagationLossModel::GetLossNlos (double /* distance2D */, double distance3D, double /* hUt */, double /* hBs */) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
double loss = 36.85 + 30 * log10 (distance3D) + 18.9 * log10 (m_frequency / 1e9);
|
||||
|
||||
return loss;
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppV2vUrbanPropagationLossModel::GetShadowingStd (Ptr<MobilityModel> /* a */, Ptr<MobilityModel> /* b */, ChannelCondition::LosConditionValue cond) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
double shadowingStd;
|
||||
|
||||
if (cond == ChannelCondition::LosConditionValue::LOS || cond == ChannelCondition::LosConditionValue::NLOSv)
|
||||
{
|
||||
shadowingStd = 3.0;
|
||||
}
|
||||
else if (cond == ChannelCondition::LosConditionValue::NLOS)
|
||||
{
|
||||
shadowingStd = 4.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Unknown channel condition");
|
||||
}
|
||||
|
||||
return shadowingStd;
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppV2vUrbanPropagationLossModel::GetShadowingCorrelationDistance (ChannelCondition::LosConditionValue cond) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
double correlationDistance;
|
||||
|
||||
// See 3GPP TR 37.885, Table 6.2.3-1
|
||||
if (cond == ChannelCondition::LosConditionValue::LOS)
|
||||
{
|
||||
correlationDistance = 10;
|
||||
}
|
||||
else if (cond == ChannelCondition::LosConditionValue::NLOSv || cond == ChannelCondition::LosConditionValue::NLOS)
|
||||
{
|
||||
correlationDistance = 13;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Unknown channel condition");
|
||||
}
|
||||
|
||||
return correlationDistance;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ThreeGppV2vHighwayPropagationLossModel);
|
||||
|
||||
TypeId
|
||||
ThreeGppV2vHighwayPropagationLossModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::ThreeGppV2vHighwayPropagationLossModel")
|
||||
.SetParent<ThreeGppV2vUrbanPropagationLossModel> ()
|
||||
.SetGroupName ("Propagation")
|
||||
.AddConstructor<ThreeGppV2vHighwayPropagationLossModel> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
ThreeGppV2vHighwayPropagationLossModel::ThreeGppV2vHighwayPropagationLossModel ()
|
||||
: ThreeGppV2vUrbanPropagationLossModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
ThreeGppV2vHighwayPropagationLossModel::~ThreeGppV2vHighwayPropagationLossModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppV2vHighwayPropagationLossModel::GetLossLos (double /* distance2D */, double distance3D, double /* hUt */, double /* hBs */) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// compute the pathloss (see 3GPP TR 37.885, Table 6.2.1-1)
|
||||
double loss = 32.4 + 20 * log10 (distance3D) + 20 * log10 (m_frequency / 1e9);
|
||||
|
||||
return loss;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
171
src/propagation/model/three-gpp-v2v-propagation-loss-model.h
Normal file
171
src/propagation/model/three-gpp-v2v-propagation-loss-model.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 SIGNET Lab, Department of Information Engineering,
|
||||
* University of Padova
|
||||
*
|
||||
* 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 THREE_GPP_V2V_PROPAGATION_LOSS_MODEL_H
|
||||
#define THREE_GPP_V2V_PROPAGATION_LOSS_MODEL_H
|
||||
|
||||
#include "three-gpp-propagation-loss-model.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \ingroup propagation
|
||||
*
|
||||
* \brief Implements the pathloss model defined in 3GPP TR 37.885, Table 6.2.1-1
|
||||
* for the Urban scenario.
|
||||
*/
|
||||
class ThreeGppV2vUrbanPropagationLossModel : public ThreeGppPropagationLossModel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppV2vUrbanPropagationLossModel ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreeGppV2vUrbanPropagationLossModel () override;
|
||||
|
||||
/**
|
||||
* \brief Copy constructor
|
||||
*
|
||||
* Defined and unimplemented to avoid misuse
|
||||
*/
|
||||
ThreeGppV2vUrbanPropagationLossModel (const ThreeGppV2vUrbanPropagationLossModel &) = delete;
|
||||
|
||||
/**
|
||||
* \brief Copy constructor
|
||||
*
|
||||
* Defined and unimplemented to avoid misuse
|
||||
* \returns the ThreeGppRmaPropagationLossModel instance
|
||||
*/
|
||||
ThreeGppV2vUrbanPropagationLossModel & operator = (const ThreeGppV2vUrbanPropagationLossModel &) = delete;
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Computes the pathloss between a and b considering that the line of
|
||||
* sight is not obstructed
|
||||
* \param distance2D the 2D distance between tx and rx in meters
|
||||
* \param distance3D the 3D distance between tx and rx in meters
|
||||
* \param hUt the height of the UT in meters
|
||||
* \param hBs the height of the BS in meters
|
||||
* \return pathloss value in dB
|
||||
*/
|
||||
virtual double GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const override;
|
||||
|
||||
/**
|
||||
* \brief Computes the pathloss between a and b considering that the line of
|
||||
* sight is obstructed by a vehicle
|
||||
* \param distance2D the 2D distance between tx and rx in meters
|
||||
* \param distance3D the 3D distance between tx and rx in meters
|
||||
* \param hUt the height of the UT in meters
|
||||
* \param hBs the height of the BS in meters
|
||||
* \return pathloss value in dB
|
||||
*/
|
||||
virtual double GetLossNlosv (double distance2D, double distance3D, double hUt, double hBs) const override;
|
||||
|
||||
/**
|
||||
* \brief Computes the pathloss between a and b considering that the line of
|
||||
* sight is obstructed by a building
|
||||
* \param distance2D the 2D distance between tx and rx in meters
|
||||
* \param distance3D the 3D distance between tx and rx in meters
|
||||
* \param hUt the height of the UT in meters
|
||||
* \param hBs the height of the BS in meters
|
||||
* \return pathloss value in dB
|
||||
*/
|
||||
virtual double GetLossNlos (double distance2D, double distance3D, double hUt, double hBs) const override;
|
||||
|
||||
/**
|
||||
* \brief Computes the additional loss due to an obstruction caused by a vehicle
|
||||
* \param distance3D the 3D distance between tx and rx in meters
|
||||
* \param hUt the height of the UT in meters
|
||||
* \param hBs the height of the BS in meters
|
||||
* \return pathloss value in dB
|
||||
*/
|
||||
double GetAdditionalNlosvLoss (double distance3D, double hUt, double hBs) const;
|
||||
|
||||
/**
|
||||
* \brief Returns the shadow fading standard deviation
|
||||
* \param a tx mobility model
|
||||
* \param b rx mobility model
|
||||
* \param cond the LOS/NLOS channel condition
|
||||
* \return shadowing std in dB
|
||||
*/
|
||||
virtual double GetShadowingStd (Ptr<MobilityModel> a, Ptr<MobilityModel> b, ChannelCondition::LosConditionValue cond) const override;
|
||||
|
||||
/**
|
||||
* \brief Returns the shadow fading correlation distance
|
||||
* \param cond the LOS/NLOS channel condition
|
||||
* \return shadowing correlation distance in meters
|
||||
*/
|
||||
virtual double GetShadowingCorrelationDistance (ChannelCondition::LosConditionValue cond) const override;
|
||||
|
||||
double m_percType3Vehicles; //!< percentage of Type 3 vehicles in the scenario (i.e., trucks)
|
||||
Ptr<UniformRandomVariable> m_uniformVar; //!< uniform random variable
|
||||
Ptr<LogNormalRandomVariable> m_logNorVar; //!< log normal random variable
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup propagation
|
||||
*
|
||||
* \brief Implements the pathloss model defined in 3GPP TR 37.885, Table 6.2.1-1
|
||||
* for the Highway scenario.
|
||||
*/
|
||||
class ThreeGppV2vHighwayPropagationLossModel : public ThreeGppV2vUrbanPropagationLossModel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppV2vHighwayPropagationLossModel ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreeGppV2vHighwayPropagationLossModel () override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Computes the pathloss between a and b considering that the line of
|
||||
* sight is not obstructed
|
||||
* \param distance2D the 2D distance between tx and rx in meters
|
||||
* \param distance3D the 3D distance between tx and rx in meters
|
||||
* \param hUt the height of the UT in meters
|
||||
* \param hBs the height of the BS in meters
|
||||
* \return pathloss value in dB
|
||||
*/
|
||||
virtual double GetLossLos (double distance2D, double distance3D, double hUt, double hBs) const override;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* THREE_GPP_V2V_PROPAGATION_LOSS_MODEL_H */
|
||||
@@ -0,0 +1,461 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
|
||||
*
|
||||
* 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/abort.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/channel-condition-model.h"
|
||||
#include "ns3/probabilistic-v2v-channel-condition-model.h"
|
||||
#include "ns3/three-gpp-v2v-propagation-loss-model.h"
|
||||
#include "ns3/constant-position-mobility-model.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/node-container.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ProbabilisticV2vChannelConditionModelsTest");
|
||||
|
||||
/**
|
||||
* Test case for the V2V Urban channel condition models using a fully
|
||||
* probabilistic model to determine LOS, NLOS and NLOSv states. The test
|
||||
* determines the channel condition multiple times,
|
||||
* estimates the LOS and NLOSv probabilities and compares them with the values
|
||||
* given by M. Boban, X.Gong, and W. Xu, “Modeling the evolution of line-of-sight
|
||||
* blockage for V2V channels,” in IEEE 84th Vehicular Technology
|
||||
* Conference (VTC-Fall), 2016. Methodology from channel-condition-model-
|
||||
* test-suite.cc is used, extended to a system with three states.
|
||||
*/
|
||||
class V2vUrbanProbChCondModelTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
V2vUrbanProbChCondModelTestCase ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~V2vUrbanProbChCondModelTestCase ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Builds the simulation scenario and perform the tests
|
||||
*/
|
||||
virtual void DoRun (void);
|
||||
|
||||
/**
|
||||
* Evaluates the channel condition between two nodes by calling the method
|
||||
* GetChannelCondition on m_condModel. If the channel condition is LOS it
|
||||
* increments m_numLos, if NLOSv it increments m_numNlosv
|
||||
* \param a the mobility model of the first node
|
||||
* \param b the mobility model of the second node
|
||||
*/
|
||||
void EvaluateChannelCondition (Ptr<MobilityModel> a, Ptr<MobilityModel> b);
|
||||
|
||||
/**
|
||||
* Struct containing the parameters for each test
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Vector m_positionA; //!< the position of the first node
|
||||
Vector m_positionB; //!< the position of the second node
|
||||
double m_pLos {0.0}; //!< LOS probability
|
||||
double m_pNlosv {0.0}; //!< NLOSv probability
|
||||
std::string m_density; //!< the vehicles density
|
||||
TypeId m_typeId; //!< the type ID of the channel condition model to be used
|
||||
} TestVector;
|
||||
|
||||
TestVectors<TestVector> m_testVectors; //!< array containing all the test vectors
|
||||
Ptr<ProbabilisticV2vUrbanChannelConditionModel> m_condModel; //!< the channel condition model
|
||||
uint64_t m_numLos {0}; //!< the number of LOS occurrences
|
||||
uint64_t m_numNlosv {0}; //!< the number of NLOSv occurrences
|
||||
double m_tolerance; //!< tolerance
|
||||
};
|
||||
|
||||
V2vUrbanProbChCondModelTestCase::V2vUrbanProbChCondModelTestCase ()
|
||||
: TestCase ("Test case for the class ProbabilisticV2vUrbanChannelConditionModel"),
|
||||
m_testVectors (),
|
||||
m_tolerance (5e-3)
|
||||
{}
|
||||
|
||||
V2vUrbanProbChCondModelTestCase::~V2vUrbanProbChCondModelTestCase ()
|
||||
{}
|
||||
|
||||
void
|
||||
V2vUrbanProbChCondModelTestCase::EvaluateChannelCondition (Ptr<MobilityModel> a, Ptr<MobilityModel> b)
|
||||
{
|
||||
Ptr<ChannelCondition> cond = m_condModel->GetChannelCondition (a, b);
|
||||
if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::LOS)
|
||||
{
|
||||
m_numLos++;
|
||||
}
|
||||
else if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::NLOSv)
|
||||
{
|
||||
m_numNlosv++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
V2vUrbanProbChCondModelTestCase::DoRun (void)
|
||||
{
|
||||
RngSeedManager::SetSeed (1);
|
||||
RngSeedManager::SetRun (1);
|
||||
|
||||
// create the test vector
|
||||
TestVector testVector;
|
||||
|
||||
// tests for the V2v Urban scenario
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (10, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, 0.8548 * exp (-0.0064 * 10.0)));
|
||||
testVector.m_typeId = ProbabilisticV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
testVector.m_pNlosv = std::min (1.0, std::max (0.0, 1 / (0.0396 * 10.0) * exp (-(log (10.0) - 5.2718) * (log (10.0) - 5.2718) / 3.4827)));
|
||||
testVector.m_density = "Low";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (100, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, 0.8548 * exp (-0.0064 * 100.0)));
|
||||
testVector.m_typeId = ProbabilisticV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
testVector.m_pNlosv = std::min (1.0, std::max (0.0, 1 / (0.0396 * 100.0) * exp (-(log (100.0) - 5.2718) * (log (100.0) - 5.2718) / 3.4827)));
|
||||
testVector.m_density = "Low";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (10, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, 0.8372 * exp (-0.0114 * 10.0)));
|
||||
testVector.m_typeId = ProbabilisticV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
testVector.m_pNlosv = std::min (1.0, std::max (0.0, 1 / (0.0312 * 10.0) * exp (-(log (10.0) - 5.0063) * (log (10.0) - 5.0063) / 2.4544)));
|
||||
testVector.m_density = "Medium";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (100, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, 0.8372 * exp (-0.0114 * 100.0)));
|
||||
testVector.m_typeId = ProbabilisticV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
testVector.m_pNlosv = std::min (1.0, std::max (0.0, 1 / (0.0312 * 100.0) * exp (-(log (100.0) - 5.0063) * (log (100.0) - 5.0063) / 2.4544)));
|
||||
testVector.m_density = "Medium";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (10, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, 0.8962 * exp (-0.017 * 10.0)));
|
||||
testVector.m_typeId = ProbabilisticV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
testVector.m_pNlosv = std::min (1.0, std::max (0.0, 1 / (0.0242 * 10.0) * exp (-(log (10.0) - 5.0115) * (log (10.0) - 5.0115) / 2.2092)));
|
||||
testVector.m_density = "High";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (100, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, 0.8962 * exp (-0.017 * 100.0)));
|
||||
testVector.m_typeId = ProbabilisticV2vUrbanChannelConditionModel::GetTypeId ();
|
||||
testVector.m_pNlosv = std::min (1.0, std::max (0.0, 1 / (0.0242 * 100.0) * exp (-(log (100.0) - 5.0115) * (log (100.0) - 5.0115) / 2.2092)));
|
||||
testVector.m_density = "High";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
// create the factory for the channel condition models
|
||||
ObjectFactory condModelFactory;
|
||||
|
||||
// create the two nodes
|
||||
NodeContainer nodes;
|
||||
nodes.Create (2);
|
||||
|
||||
// create the mobility models
|
||||
Ptr<MobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
|
||||
Ptr<MobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
|
||||
|
||||
// aggregate the nodes and the mobility models
|
||||
nodes.Get (0)->AggregateObject (a);
|
||||
nodes.Get (1)->AggregateObject (b);
|
||||
|
||||
// Get the channel condition multiple times and compute the LOS probability
|
||||
uint32_t numberOfReps = 500000;
|
||||
for (uint32_t i = 0; i < m_testVectors.GetN (); ++i)
|
||||
{
|
||||
testVector = m_testVectors.Get (i);
|
||||
|
||||
// set the distance between the two nodes
|
||||
a->SetPosition (testVector.m_positionA);
|
||||
b->SetPosition (testVector.m_positionB);
|
||||
|
||||
// create the channel condition model
|
||||
condModelFactory.SetTypeId (testVector.m_typeId);
|
||||
m_condModel = condModelFactory.Create<ProbabilisticV2vUrbanChannelConditionModel> ();
|
||||
m_condModel->SetAttribute ("UpdatePeriod", TimeValue (MilliSeconds (9)));
|
||||
m_condModel->AssignStreams (1);
|
||||
m_condModel->SetAttribute ("Density", StringValue (testVector.m_density));
|
||||
|
||||
m_numLos = 0;
|
||||
m_numNlosv = 0;
|
||||
for (uint32_t j = 0; j < numberOfReps; j++)
|
||||
{
|
||||
Simulator::Schedule (MilliSeconds (10 * j), &V2vUrbanProbChCondModelTestCase::EvaluateChannelCondition, this, a, b);
|
||||
}
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
double resultPlos = double (m_numLos) / double (numberOfReps);
|
||||
double resultPnlosv = double (m_numNlosv) / double (numberOfReps);
|
||||
NS_LOG_DEBUG (testVector.m_typeId << " a pos " << testVector.m_positionA << " b pos " << testVector.m_positionB << " numLos " << m_numLos << " numberOfReps " << numberOfReps << " resultPlos " << resultPlos << " ref " << testVector.m_pLos);
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (resultPlos, testVector.m_pLos, m_tolerance, "Got unexpected LOS probability");
|
||||
NS_LOG_DEBUG (testVector.m_typeId << " a pos " << testVector.m_positionA << " b pos " << testVector.m_positionB << " numNlosv " << m_numNlosv << " numberOfReps " << numberOfReps << " resultPnlosv " << resultPnlosv << " ref " << testVector.m_pNlosv);
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (resultPnlosv, testVector.m_pNlosv, m_tolerance, "Got unexpected NLOSv probability");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case for the V2V Highway channel condition models using a fully
|
||||
* probabilistic model to determine LOS, NLOS and NLOSv states. The test
|
||||
* determines the channel condition multiple times,
|
||||
* estimates the LOS and NLOS probabilities and compares them with the values
|
||||
* given by M. Boban, X.Gong, and W. Xu, “Modeling the evolution of line-of-sight
|
||||
* blockage for V2V channels,” in IEEE 84th Vehicular Technology
|
||||
* Conference (VTC-Fall), 2016. Methodology from channel-condition-model-
|
||||
* test-suite.cc is used, extended to a system with three states.
|
||||
*/
|
||||
class V2vHighwayProbChCondModelTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
V2vHighwayProbChCondModelTestCase ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~V2vHighwayProbChCondModelTestCase ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Builds the simulation scenario and perform the tests
|
||||
*/
|
||||
virtual void DoRun (void);
|
||||
|
||||
/**
|
||||
* Evaluates the channel condition between two nodes by calling the method
|
||||
* GetChannelCondition on m_condModel. If the channel condition is LOS it
|
||||
* increments m_numLos, if NLOS it increments m_numNlos
|
||||
* \param a the mobility model of the first node
|
||||
* \param b the mobility model of the second node
|
||||
*/
|
||||
void EvaluateChannelCondition (Ptr<MobilityModel> a, Ptr<MobilityModel> b);
|
||||
|
||||
/**
|
||||
* Struct containing the parameters for each test
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Vector m_positionA; //!< the position of the first node
|
||||
Vector m_positionB; //!< the position of the second node
|
||||
double m_pLos {0.0}; //!< LOS probability
|
||||
double m_pNlos {0.0}; //!< NLOS probability
|
||||
std::string m_density; //!< the vehicles density
|
||||
TypeId m_typeId; //!< the type ID of the channel condition model to be used
|
||||
} TestVector;
|
||||
|
||||
TestVectors<TestVector> m_testVectors; //!< array containing all the test vectors
|
||||
Ptr<ProbabilisticV2vHighwayChannelConditionModel> m_condModel; //!< the channel condition model
|
||||
uint64_t m_numLos {0}; //!< the number of LOS occurrences
|
||||
uint64_t m_numNlos {0}; //!< the number of NLOS occurrences
|
||||
double m_tolerance; //!< tolerance
|
||||
};
|
||||
|
||||
V2vHighwayProbChCondModelTestCase::V2vHighwayProbChCondModelTestCase ()
|
||||
: TestCase ("Test case for the class ProbabilisticV2vHighwayChannelConditionModel"),
|
||||
m_testVectors (),
|
||||
m_tolerance (5e-3)
|
||||
{}
|
||||
|
||||
V2vHighwayProbChCondModelTestCase::~V2vHighwayProbChCondModelTestCase ()
|
||||
{}
|
||||
|
||||
void
|
||||
V2vHighwayProbChCondModelTestCase::EvaluateChannelCondition (Ptr<MobilityModel> a, Ptr<MobilityModel> b)
|
||||
{
|
||||
Ptr<ChannelCondition> cond = m_condModel->GetChannelCondition (a, b);
|
||||
if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::LOS)
|
||||
{
|
||||
m_numLos++;
|
||||
}
|
||||
else if (cond->GetLosCondition () == ChannelCondition::LosConditionValue::NLOS)
|
||||
{
|
||||
m_numNlos++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
V2vHighwayProbChCondModelTestCase::DoRun (void)
|
||||
{
|
||||
RngSeedManager::SetSeed (1);
|
||||
RngSeedManager::SetRun (1);
|
||||
|
||||
// create the test vector
|
||||
TestVector testVector;
|
||||
|
||||
// tests for the V2v Highway scenario
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (10, 0, 1.6);
|
||||
double aLos = 1.5e-6;
|
||||
double bLos = -0.0015;
|
||||
double cLos = 1.0;
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, aLos * 10.0 * 10.0 + bLos * 10.0 + cLos));
|
||||
testVector.m_typeId = ProbabilisticV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
double aNlos = -2.9e-7;
|
||||
double bNlos = 0.00059;
|
||||
double cNlos = 0.0017;
|
||||
testVector.m_pNlos = std::min (1.0, std::max (0.0, aNlos * 10.0 * 10.0 + bNlos * 10.0 + cNlos));
|
||||
testVector.m_density = "Low";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (100, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, aLos * 100.0 * 100.0 + bLos * 100.0 + cLos));
|
||||
testVector.m_typeId = ProbabilisticV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
testVector.m_pNlos = std::min (1.0, std::max (0.0, aNlos * 100.0 * 100.0 + bNlos * 100.0 + cNlos));
|
||||
testVector.m_density = "Low";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (10, 0, 1.6);
|
||||
aLos = 2.7e-6;
|
||||
bLos = -0.0025;
|
||||
cLos = 1.0;
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, aLos * 10.0 * 10.0 + bLos * 10.0 + cLos));
|
||||
testVector.m_typeId = ProbabilisticV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
aNlos = -3.7e-7;
|
||||
bNlos = 0.00061;
|
||||
cNlos = 0.015;
|
||||
testVector.m_pNlos = std::min (1.0, std::max (0.0, aNlos * 10.0 * 10.0 + bNlos * 10.0 + cNlos));
|
||||
testVector.m_density = "Medium";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (100, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, aLos * 100.0 * 100.0 + bLos * 100.0 + cLos));
|
||||
testVector.m_typeId = ProbabilisticV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
testVector.m_pNlos = std::min (1.0, std::max (0.0, aNlos * 100.0 * 100.0 + bNlos * 100.0 + cNlos));
|
||||
testVector.m_density = "Medium";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (10, 0, 1.6);
|
||||
aLos = 3.2e-6;
|
||||
bLos = -0.003;
|
||||
cLos = 1.0;
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, aLos * 10.0 * 10.0 + bLos * 10.0 + cLos));
|
||||
testVector.m_typeId = ProbabilisticV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
aNlos = -4.1e-7;
|
||||
bNlos = 0.00067;
|
||||
cNlos = 0.0;
|
||||
testVector.m_pNlos = std::min (1.0, std::max (0.0, aNlos * 10.0 * 10.0 + bNlos * 10.0 + cNlos));
|
||||
testVector.m_density = "High";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_positionA = Vector (0, 0, 1.6);
|
||||
testVector.m_positionB = Vector (100, 0, 1.6);
|
||||
testVector.m_pLos = std::min (1.0, std::max (0.0, aLos * 100.0 * 100.0 + bLos * 100.0 + cLos));
|
||||
testVector.m_typeId = ProbabilisticV2vHighwayChannelConditionModel::GetTypeId ();
|
||||
testVector.m_pNlos = std::min (1.0, std::max (0.0, aNlos * 100.0 * 100.0 + bNlos * 100.0 + cNlos));
|
||||
testVector.m_density = "High";
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
// create the factory for the channel condition models
|
||||
ObjectFactory condModelFactory;
|
||||
|
||||
// create the two nodes
|
||||
NodeContainer nodes;
|
||||
nodes.Create (2);
|
||||
|
||||
// create the mobility models
|
||||
Ptr<MobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
|
||||
Ptr<MobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
|
||||
|
||||
// aggregate the nodes and the mobility models
|
||||
nodes.Get (0)->AggregateObject (a);
|
||||
nodes.Get (1)->AggregateObject (b);
|
||||
|
||||
// Get the channel condition multiple times and compute the LOS probability
|
||||
uint32_t numberOfReps = 500000;
|
||||
for (uint32_t i = 0; i < m_testVectors.GetN (); ++i)
|
||||
{
|
||||
testVector = m_testVectors.Get (i);
|
||||
|
||||
// set the distance between the two nodes
|
||||
a->SetPosition (testVector.m_positionA);
|
||||
b->SetPosition (testVector.m_positionB);
|
||||
|
||||
// create the channel condition model
|
||||
condModelFactory.SetTypeId (testVector.m_typeId);
|
||||
m_condModel = condModelFactory.Create<ProbabilisticV2vHighwayChannelConditionModel> ();
|
||||
m_condModel->SetAttribute ("UpdatePeriod", TimeValue (MilliSeconds (9)));
|
||||
m_condModel->AssignStreams (1);
|
||||
m_condModel->SetAttribute ("Density", StringValue (testVector.m_density));
|
||||
|
||||
m_numLos = 0;
|
||||
m_numNlos = 0;
|
||||
for (uint32_t j = 0; j < numberOfReps; j++)
|
||||
{
|
||||
Simulator::Schedule (MilliSeconds (10 * j), &V2vHighwayProbChCondModelTestCase::EvaluateChannelCondition, this, a, b);
|
||||
}
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
double resultPlos = double (m_numLos) / double (numberOfReps);
|
||||
double resultPnlos = double (m_numNlos) / double (numberOfReps);
|
||||
NS_LOG_DEBUG (testVector.m_typeId << " a pos " << testVector.m_positionA << " b pos " << testVector.m_positionB << " numLos " << m_numLos << " numberOfReps " << numberOfReps << " resultPlos " << resultPlos << " ref " << testVector.m_pLos);
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (resultPlos, testVector.m_pLos, m_tolerance, "Got unexpected LOS probability");
|
||||
NS_LOG_DEBUG (testVector.m_typeId << " a pos " << testVector.m_positionA << " b pos " << testVector.m_positionB << " numNlos " << m_numNlos << " numberOfReps " << numberOfReps << " resultPnlos " << resultPnlos << " ref " << testVector.m_pNlos);
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (resultPnlos, testVector.m_pNlos, m_tolerance, "Got unexpected NLOS probability");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test suite for the probabilistic V2V channel condition model
|
||||
*
|
||||
* The tests V2vUrbanProbChCondModelTestCase and
|
||||
* V2vHighwayProbChCondModelTestCase test a fully probabilistic
|
||||
* model for V2V channel condition, for Urban and Highway V2V scenarios,
|
||||
* respectively. Basically, the model determines NLOS/LOS/NLOSv state based
|
||||
* on probability formulas, derived from: M. Boban, X.Gong, and W. Xu,
|
||||
* “Modeling the evolution of line-of-sight blockage for V2V channels,”
|
||||
* in IEEE 84th Vehicular Technology Conference (VTC-Fall), 2016.
|
||||
*
|
||||
*/
|
||||
class ProbabilisticV2vChCondModelsTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
ProbabilisticV2vChCondModelsTestSuite ();
|
||||
};
|
||||
|
||||
ProbabilisticV2vChCondModelsTestSuite::ProbabilisticV2vChCondModelsTestSuite ()
|
||||
: TestSuite ("probabilistic-v2v-channel-condition-model", SYSTEM)
|
||||
{
|
||||
AddTestCase (new V2vUrbanProbChCondModelTestCase, TestCase::QUICK); // test for a fully probabilistic model (NLOS vs LOS vs NLOSv), in V2V urban scenario
|
||||
AddTestCase (new V2vHighwayProbChCondModelTestCase, TestCase::QUICK); // test for a fully probabilistic model (NLOS vs LOS vs NLOSv), in V2V highway scenario*/
|
||||
}
|
||||
|
||||
static ProbabilisticV2vChCondModelsTestSuite probabilisticV2vChCondModelsTestSuite;
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/channel-condition-model.h"
|
||||
#include "ns3/three-gpp-propagation-loss-model.h"
|
||||
#include "ns3/three-gpp-v2v-propagation-loss-model.h"
|
||||
#include "ns3/constant-position-mobility-model.h"
|
||||
#include "ns3/constant-velocity-mobility-model.h"
|
||||
#include "ns3/mobility-helper.h"
|
||||
@@ -656,6 +657,312 @@ ThreeGppIndoorOfficePropagationLossModelTestCase::DoRun (void)
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case for the class ThreeGppV2vUrbanPropagationLossModel.
|
||||
* It computes the pathloss between two nodes and compares it with the value
|
||||
* obtained using the formula in 3GPP TR 37.885 Table 6.2.1-1 for v2v
|
||||
* communications (sidelink).
|
||||
*
|
||||
* Note that 3GPP TR 37.885 defines 3 different channel states for vehicular
|
||||
* environments: LOS, NLOS, and NLOSv, the latter representing the case in which
|
||||
* the LOS path is blocked by other vehicles in the scenario. However, for
|
||||
* computing the pathloss, only the two states are considered: LOS/NLOSv or NLOS
|
||||
* (see TR 37.885 Section 6.2.1). In case of NLOSv, an additional vehicle
|
||||
* blockage loss may be added, according to a log-normal random variable.
|
||||
* Here, we test both conditions: LOS/NLOSv (without vehicle blockage
|
||||
* loss) and NLOS.
|
||||
*/
|
||||
class ThreeGppV2vUrbanPropagationLossModelTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppV2vUrbanPropagationLossModelTestCase ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreeGppV2vUrbanPropagationLossModelTestCase ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Build the simulation scenario and run the tests
|
||||
*/
|
||||
virtual void DoRun (void);
|
||||
|
||||
/**
|
||||
* Struct containing the parameters for each test
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double m_distance; //!< 2D distance between UT and BS in meters
|
||||
bool m_isLos; //!< if true LOS/NLOSv, if false NLOS
|
||||
double m_frequency; //!< carrier frequency in Hz
|
||||
double m_pt; //!< transmitted power in dBm
|
||||
double m_pr; //!< received power in dBm
|
||||
} TestVector;
|
||||
|
||||
TestVectors<TestVector> m_testVectors; //!< array containing all the test vectors
|
||||
double m_tolerance; //!< tolerance
|
||||
};
|
||||
|
||||
ThreeGppV2vUrbanPropagationLossModelTestCase::ThreeGppV2vUrbanPropagationLossModelTestCase ()
|
||||
: TestCase ("Test for the ThreeGppV2vUrbanPropagationLossModel class."),
|
||||
m_testVectors (),
|
||||
m_tolerance (5e-2)
|
||||
{
|
||||
}
|
||||
|
||||
ThreeGppV2vUrbanPropagationLossModelTestCase::~ThreeGppV2vUrbanPropagationLossModelTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppV2vUrbanPropagationLossModelTestCase::DoRun (void)
|
||||
{
|
||||
TestVector testVector;
|
||||
|
||||
testVector.m_distance = 10.0;
|
||||
testVector.m_isLos = true;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -68.1913;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_distance = 100.0;
|
||||
testVector.m_isLos = true;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -84.8913;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_distance = 1000.0;
|
||||
testVector.m_isLos = true;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -101.5913;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_distance = 10.0;
|
||||
testVector.m_isLos = false;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -80.0605;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_distance = 100.0;
|
||||
testVector.m_isLos = false;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -110.0605;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_distance = 1000.0;
|
||||
testVector.m_isLos = false;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -140.0605;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
// Create the nodes for BS and UT
|
||||
NodeContainer nodes;
|
||||
nodes.Create (2);
|
||||
|
||||
// Create the mobility models
|
||||
Ptr<MobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
|
||||
nodes.Get (0)->AggregateObject (a);
|
||||
Ptr<MobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
|
||||
nodes.Get (1)->AggregateObject (b);
|
||||
|
||||
// Use a deterministic channel condition model
|
||||
Ptr<ChannelConditionModel> losCondModel = CreateObject<AlwaysLosChannelConditionModel> ();
|
||||
Ptr<ChannelConditionModel> nlosCondModel = CreateObject<NeverLosChannelConditionModel> ();
|
||||
|
||||
// Create the propagation loss model
|
||||
Ptr<ThreeGppPropagationLossModel> lossModel = CreateObject<ThreeGppV2vUrbanPropagationLossModel> ();
|
||||
lossModel->SetAttribute ("ShadowingEnabled", BooleanValue (false)); // disable the shadow fading
|
||||
|
||||
for (uint32_t i = 0; i < m_testVectors.GetN (); i++)
|
||||
{
|
||||
TestVector testVector = m_testVectors.Get (i);
|
||||
|
||||
Vector posUe1 = Vector (0.0, 0.0, 1.6);
|
||||
Vector posUe2 = Vector (testVector.m_distance, 0.0, 1.6);
|
||||
|
||||
// set the LOS or NLOS condition
|
||||
if (testVector.m_isLos)
|
||||
{
|
||||
lossModel->SetChannelConditionModel (losCondModel);
|
||||
}
|
||||
else
|
||||
{
|
||||
lossModel->SetChannelConditionModel (nlosCondModel);
|
||||
}
|
||||
|
||||
a->SetPosition (posUe1);
|
||||
b->SetPosition (posUe2);
|
||||
|
||||
lossModel->SetAttribute ("Frequency", DoubleValue (testVector.m_frequency));
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (lossModel->CalcRxPower (testVector.m_pt, a, b), testVector.m_pr, m_tolerance, "Got unexpected rcv power");
|
||||
}
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case for the class ThreeGppV2vHighwayPropagationLossModel.
|
||||
* It computes the pathloss between two nodes and compares it with the value
|
||||
* obtained using the formula in 3GPP TR 37.885 Table 6.2.1-1 for v2v
|
||||
* communications (sidelink).
|
||||
*
|
||||
* Note that 3GPP TR 37.885 defines 3 different channel states for vehicular
|
||||
* environments: LOS, NLOS and NLOSv, the latter representing the case in which
|
||||
* the LOS path is blocked by other vehicles in the scenario. However, for
|
||||
* computing the pathloss, only two states are considered: LOS/NLOSv or NLOS
|
||||
* (see TR 37.885 Section 6.2.1). In case of NLOSv, an additional vehicle
|
||||
* blockage loss may be added, according to a log-normal random variable.
|
||||
* Here, we test both conditions: LOS/NLOSv (without vehicle blockage
|
||||
* loss) and NLOS.
|
||||
*/
|
||||
class ThreeGppV2vHighwayPropagationLossModelTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppV2vHighwayPropagationLossModelTestCase ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreeGppV2vHighwayPropagationLossModelTestCase ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Build the simulation scenario and run the tests
|
||||
*/
|
||||
virtual void DoRun (void);
|
||||
|
||||
/**
|
||||
* Struct containing the parameters for each test
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double m_distance; //!< 2D distance between UT and BS in meters
|
||||
bool m_isLos; //!< if true LOS/NLOSv, if false NLOS
|
||||
double m_frequency; //!< carrier frequency in Hz
|
||||
double m_pt; //!< transmitted power in dBm
|
||||
double m_pr; //!< received power in dBm
|
||||
} TestVector;
|
||||
|
||||
TestVectors<TestVector> m_testVectors; //!< array containing all the test vectors
|
||||
double m_tolerance; //!< tolerance
|
||||
};
|
||||
|
||||
ThreeGppV2vHighwayPropagationLossModelTestCase::ThreeGppV2vHighwayPropagationLossModelTestCase ()
|
||||
: TestCase ("Test for the ThreeGppV2vHighwayPropagationLossModel"),
|
||||
m_testVectors (),
|
||||
m_tolerance (5e-2)
|
||||
{
|
||||
}
|
||||
|
||||
ThreeGppV2vHighwayPropagationLossModelTestCase::~ThreeGppV2vHighwayPropagationLossModelTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppV2vHighwayPropagationLossModelTestCase::DoRun (void)
|
||||
{
|
||||
TestVector testVector;
|
||||
|
||||
testVector.m_distance = 10.0;
|
||||
testVector.m_isLos = true;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -66.3794;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_distance = 100.0;
|
||||
testVector.m_isLos = true;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -86.3794;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_distance = 1000.0;
|
||||
testVector.m_isLos = true;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -106.3794;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_distance = 10.0;
|
||||
testVector.m_isLos = false;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -80.0605;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_distance = 100.0;
|
||||
testVector.m_isLos = false;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -110.0605;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_distance = 1000.0;
|
||||
testVector.m_isLos = false;
|
||||
testVector.m_frequency = 5.0e9;
|
||||
testVector.m_pt = 0.0;
|
||||
testVector.m_pr = -140.0605;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
// Create the nodes for BS and UT
|
||||
NodeContainer nodes;
|
||||
nodes.Create (2);
|
||||
|
||||
// Create the mobility models
|
||||
Ptr<MobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
|
||||
nodes.Get (0)->AggregateObject (a);
|
||||
Ptr<MobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
|
||||
nodes.Get (1)->AggregateObject (b);
|
||||
|
||||
// Use a deterministic channel condition model
|
||||
Ptr<ChannelConditionModel> losCondModel = CreateObject<AlwaysLosChannelConditionModel> ();
|
||||
Ptr<ChannelConditionModel> nlosCondModel = CreateObject<NeverLosChannelConditionModel> ();
|
||||
|
||||
// Create the propagation loss model
|
||||
Ptr<ThreeGppPropagationLossModel> lossModel = CreateObject<ThreeGppV2vHighwayPropagationLossModel> ();
|
||||
lossModel->SetAttribute ("ShadowingEnabled", BooleanValue (false)); // disable the shadow fading
|
||||
|
||||
for (uint32_t i = 0; i < m_testVectors.GetN (); i++)
|
||||
{
|
||||
TestVector testVector = m_testVectors.Get (i);
|
||||
|
||||
Vector posUe1 = Vector (0.0, 0.0, 1.6);
|
||||
Vector posUe2 = Vector (testVector.m_distance, 0.0, 1.6);
|
||||
|
||||
// set the LOS or NLOS condition
|
||||
if (testVector.m_isLos)
|
||||
{
|
||||
lossModel->SetChannelConditionModel (losCondModel);
|
||||
}
|
||||
else
|
||||
{
|
||||
lossModel->SetChannelConditionModel (nlosCondModel);
|
||||
}
|
||||
|
||||
a->SetPosition (posUe1);
|
||||
b->SetPosition (posUe2);
|
||||
|
||||
lossModel->SetAttribute ("Frequency", DoubleValue (testVector.m_frequency));
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (lossModel->CalcRxPower (testVector.m_pt, a, b), testVector.m_pr, m_tolerance, "Got unexpected rcv power");
|
||||
}
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
// Test to check if the shadowing fading is correctly computed
|
||||
class ThreeGppShadowingTestCase : public TestCase
|
||||
{
|
||||
@@ -780,8 +1087,8 @@ ThreeGppShadowingTestCase::DoRun (void)
|
||||
{
|
||||
// The test scenario is composed of two nodes, one fixed
|
||||
// at position (0,0) and the other moving with constant velocity from
|
||||
// position (0,50) to position (200,50). A building is placed in such a way
|
||||
// that the channel condition changes from LOS to NLOS when the second node
|
||||
// position (0,50) to position (200,50).
|
||||
// The channel condition changes from LOS to NLOS when the second node
|
||||
// reaches position (100,50).
|
||||
// Each experiment computes the propagation loss between the two nodes
|
||||
// every second, until the final position is reached, and saves the
|
||||
@@ -833,6 +1140,22 @@ ThreeGppShadowingTestCase::DoRun (void)
|
||||
testVector.m_shadowingStdLos = 3;
|
||||
testVector.m_shadowingStdNlos = 8.03;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_propagationLossModelType = "ns3::ThreeGppV2vUrbanPropagationLossModel";
|
||||
testVector.m_hBs = 1.6;
|
||||
testVector.m_hUt = 1.6;
|
||||
testVector.m_distance = 50;
|
||||
testVector.m_shadowingStdLos = 3;
|
||||
testVector.m_shadowingStdNlos = 4;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
testVector.m_propagationLossModelType = "ns3::ThreeGppV2vHighwayPropagationLossModel";
|
||||
testVector.m_hBs = 1.6;
|
||||
testVector.m_hUt = 1.6;
|
||||
testVector.m_distance = 50;
|
||||
testVector.m_shadowingStdLos = 3;
|
||||
testVector.m_shadowingStdNlos = 4;
|
||||
m_testVectors.Add (testVector);
|
||||
|
||||
uint16_t numSamples = 250;
|
||||
|
||||
@@ -897,6 +1220,8 @@ ThreeGppPropagationLossModelsTestSuite::ThreeGppPropagationLossModelsTestSuite (
|
||||
AddTestCase (new ThreeGppUmaPropagationLossModelTestCase, TestCase::QUICK);
|
||||
AddTestCase (new ThreeGppUmiPropagationLossModelTestCase, TestCase::QUICK);
|
||||
AddTestCase (new ThreeGppIndoorOfficePropagationLossModelTestCase, TestCase::QUICK);
|
||||
AddTestCase (new ThreeGppV2vUrbanPropagationLossModelTestCase, TestCase::QUICK);
|
||||
AddTestCase (new ThreeGppV2vHighwayPropagationLossModelTestCase, TestCase::QUICK);
|
||||
AddTestCase (new ThreeGppShadowingTestCase, TestCase::QUICK);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ def build(bld):
|
||||
'model/itu-r-1411-nlos-over-rooftop-propagation-loss-model.cc',
|
||||
'model/kun-2600-mhz-propagation-loss-model.cc',
|
||||
'model/channel-condition-model.cc',
|
||||
'model/probabilistic-v2v-channel-condition-model.cc',
|
||||
'model/three-gpp-propagation-loss-model.cc',
|
||||
'model/three-gpp-v2v-propagation-loss-model.cc',
|
||||
]
|
||||
|
||||
module_test = bld.create_ns3_module_test_library('propagation')
|
||||
@@ -26,6 +28,7 @@ def build(bld):
|
||||
'test/itu-r-1411-nlos-over-rooftop-test-suite.cc',
|
||||
'test/channel-condition-model-test-suite.cc',
|
||||
'test/three-gpp-propagation-loss-model-test-suite.cc',
|
||||
'test/probabilistic-v2v-channel-condition-model-test.cc',
|
||||
]
|
||||
|
||||
# Tests encapsulating example programs should be listed here
|
||||
@@ -49,7 +52,9 @@ def build(bld):
|
||||
'model/itu-r-1411-nlos-over-rooftop-propagation-loss-model.h',
|
||||
'model/kun-2600-mhz-propagation-loss-model.h',
|
||||
'model/channel-condition-model.h',
|
||||
'model/probabilistic-v2v-channel-condition-model.h',
|
||||
'model/three-gpp-propagation-loss-model.h',
|
||||
'model/three-gpp-v2v-propagation-loss-model.h',
|
||||
]
|
||||
|
||||
if (bld.env['ENABLE_EXAMPLES']):
|
||||
|
||||
@@ -586,6 +586,8 @@ the given geographic origin point, and is tested in the ``rand-cart-around-geo``
|
||||
test suite by verifying that the generated points do not exceed the given
|
||||
maximum distance radius from the origin point.
|
||||
|
||||
.. _sec-3gpp-fast-fading-model:
|
||||
|
||||
3GPP TR 38.901 fast fading model
|
||||
================================
|
||||
The framework described by TR 38.901 [TR38901]_ is a 3D statistical Spatial
|
||||
@@ -687,7 +689,14 @@ applies it to the PSD of the transmitted signal to obtain the received PSD.
|
||||
To compute the sub-band gain, it accounts for the Doppler phenomenon and the
|
||||
time dispersion effect on each cluster.
|
||||
In order to reduce the computational load, the Doppler component of each
|
||||
cluster is computed considering only the central ray.
|
||||
cluster is computed considering only the central ray.
|
||||
Also, as specified :ref:`here <sec-3gpp-v2v-ff>`, it is possible to account for
|
||||
the effect of environmental scattering following the model described in Sec. 6.2.3
|
||||
of 3GPP TR 37.885.
|
||||
This is done by deviating the Doppler frequency by a random value, whose
|
||||
distribution depends on the parameter :math:`v_{scatt}`.
|
||||
The value of :math:`v_{scatt}` can be configured using the attribute "vScatt"
|
||||
(by default it is set to 0, so that the scattering effect is not considered).
|
||||
|
||||
ThreeGppChannelModel
|
||||
####################
|
||||
|
||||
@@ -236,7 +236,7 @@ ThreeGppChannelModel::GetTypeId (void)
|
||||
DoubleValue (1),
|
||||
MakeDoubleAccessor (&ThreeGppChannelModel::m_blockerSpeed),
|
||||
MakeDoubleChecker<double> ())
|
||||
;
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
@@ -273,9 +273,11 @@ void
|
||||
ThreeGppChannelModel::SetScenario (const std::string &scenario)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_ASSERT_MSG (scenario == "RMa" || scenario == "UMa" || scenario == "UMi-StreetCanyon" ||
|
||||
scenario == "InH-OfficeOpen" || scenario == "InH-OfficeMixed",
|
||||
"Unknown scenario, choose between RMa, UMa, UMi-StreetCanyon, InH-OfficeOpen or InH-OfficeMixed");
|
||||
NS_ASSERT_MSG (scenario == "RMa" || scenario == "UMa" || scenario == "UMi-StreetCanyon"
|
||||
|| scenario == "InH-OfficeOpen" || scenario == "InH-OfficeMixed"
|
||||
|| scenario == "V2V-Urban" || scenario == "V2V-Highway",
|
||||
"Unknown scenario, choose between RMa, UMa, UMi-StreetCanyon,"
|
||||
"InH-OfficeOpen, InH-OfficeMixed, V2V-Urban or V2V-Highway");
|
||||
m_scenario = scenario;
|
||||
}
|
||||
|
||||
@@ -287,7 +289,7 @@ ThreeGppChannelModel::GetScenario () const
|
||||
}
|
||||
|
||||
Ptr<const ThreeGppChannelModel::ParamsTable>
|
||||
ThreeGppChannelModel::GetThreeGppTable (bool los, bool o2i, double hBS, double hUT, double distance2D) const
|
||||
ThreeGppChannelModel::GetThreeGppTable (Ptr<const ChannelCondition> channelCondition, double hBS, double hUT, double distance2D) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
@@ -298,6 +300,9 @@ ThreeGppChannelModel::GetThreeGppTable (bool los, bool o2i, double hBS, double h
|
||||
// uLgASA, sigLgASA, uLgZSA, sigLgZSA, uLgZSD, sigLgZSD, offsetZOD,
|
||||
// cDS, cASD, cASA, cZSA, uK, sigK, rTau, uXpr, sigXpr, shadowingStd
|
||||
|
||||
bool los = channelCondition->IsLos ();
|
||||
bool o2i = channelCondition->IsO2i ();
|
||||
|
||||
// In NLOS case, parameter uK and sigK are not used and they are set to 0
|
||||
if (m_scenario == "RMa")
|
||||
{
|
||||
@@ -468,7 +473,7 @@ ThreeGppChannelModel::GetThreeGppTable (bool los, bool o2i, double hBS, double h
|
||||
table3gpp->m_uLgZSD = uLgZSD;
|
||||
table3gpp->m_sigLgZSD = 0.49;
|
||||
table3gpp->m_offsetZOD = offsetZOD;
|
||||
table3gpp->m_cDS = std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;;
|
||||
table3gpp->m_cDS = std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;
|
||||
table3gpp->m_cASD = 2;
|
||||
table3gpp->m_cASA = 15;
|
||||
table3gpp->m_cZSA = 7;
|
||||
@@ -708,6 +713,228 @@ ThreeGppChannelModel::GetThreeGppTable (bool los, bool o2i, double hBS, double h
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_scenario == "V2V-Urban")
|
||||
{
|
||||
if (channelCondition->IsLos ())
|
||||
{
|
||||
// 3GPP mentioned that 3.91 ns should be used when the Cluster DS (cDS)
|
||||
// entry is N/A.
|
||||
table3gpp->m_numOfCluster = 12;
|
||||
table3gpp->m_raysPerCluster = 20;
|
||||
table3gpp->m_uLgDS = -0.2 * log10 (1 + fcGHz) - 7.5;
|
||||
table3gpp->m_sigLgDS = 0.1;
|
||||
table3gpp->m_uLgASD = -0.1 * log10 (1 + fcGHz) + 1.6;
|
||||
table3gpp->m_sigLgASD = 0.1;
|
||||
table3gpp->m_uLgASA = -0.1 * log10 (1 + fcGHz) + 1.6;
|
||||
table3gpp->m_sigLgASA = 0.1;
|
||||
table3gpp->m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73,
|
||||
table3gpp->m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34,
|
||||
table3gpp->m_uLgZSD = -0.1 * log10 (1 + fcGHz) + 0.73;
|
||||
table3gpp->m_sigLgZSD = -0.04 * log10 (1 + fcGHz) + 0.34;
|
||||
table3gpp->m_offsetZOD = 0;
|
||||
table3gpp->m_cDS = 5;
|
||||
table3gpp->m_cASD = 17;
|
||||
table3gpp->m_cASA = 17;
|
||||
table3gpp->m_cZSA = 7;
|
||||
table3gpp->m_uK = 3.48;
|
||||
table3gpp->m_sigK = 2;
|
||||
table3gpp->m_rTau = 3;
|
||||
table3gpp->m_uXpr = 9;
|
||||
table3gpp->m_sigXpr = 3;
|
||||
table3gpp->m_perClusterShadowingStd = 4;
|
||||
|
||||
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 (channelCondition->IsNlos ())
|
||||
{
|
||||
table3gpp->m_numOfCluster = 19;
|
||||
table3gpp->m_raysPerCluster = 20;
|
||||
table3gpp->m_uLgDS = -0.3 * log10 (1 + fcGHz) - 7;
|
||||
table3gpp->m_sigLgDS = 0.28;
|
||||
table3gpp->m_uLgASD = -0.08 * log10 (1 + fcGHz) + 1.81;
|
||||
table3gpp->m_sigLgASD = 0.05 * log10 (1 + fcGHz) + 0.3;
|
||||
table3gpp->m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
|
||||
table3gpp->m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
|
||||
table3gpp->m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92,
|
||||
table3gpp->m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
|
||||
table3gpp->m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
|
||||
table3gpp->m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
|
||||
table3gpp->m_offsetZOD = 0;
|
||||
table3gpp->m_cDS = 11;
|
||||
table3gpp->m_cASD = 22;
|
||||
table3gpp->m_cASA = 22;
|
||||
table3gpp->m_cZSA = 7;
|
||||
table3gpp->m_uK = 0; // N/A
|
||||
table3gpp->m_sigK = 0; // N/A
|
||||
table3gpp->m_rTau = 2.1;
|
||||
table3gpp->m_uXpr = 8;
|
||||
table3gpp->m_sigXpr = 3;
|
||||
table3gpp->m_perClusterShadowingStd = 4;
|
||||
|
||||
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 (channelCondition->IsNlosv ())
|
||||
{
|
||||
table3gpp->m_numOfCluster = 19;
|
||||
table3gpp->m_raysPerCluster = 20;
|
||||
table3gpp->m_uLgDS = -0.4 * log10 (1 + fcGHz) - 7;
|
||||
table3gpp->m_sigLgDS = 0.1;
|
||||
table3gpp->m_uLgASD = -0.1 * log10 (1 + fcGHz) + 1.7;
|
||||
table3gpp->m_sigLgASD = 0.1;
|
||||
table3gpp->m_uLgASA = -0.1 * log10 (1 + fcGHz) + 1.7;
|
||||
table3gpp->m_sigLgASA = 0.1;
|
||||
table3gpp->m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
|
||||
table3gpp->m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
|
||||
table3gpp->m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
|
||||
table3gpp->m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
|
||||
table3gpp->m_offsetZOD = 0;
|
||||
table3gpp->m_cDS = 11;
|
||||
table3gpp->m_cASD = 22;
|
||||
table3gpp->m_cASA = 22;
|
||||
table3gpp->m_cZSA = 7;
|
||||
table3gpp->m_uK = 0;
|
||||
table3gpp->m_sigK = 4.5;
|
||||
table3gpp->m_rTau = 2.1;
|
||||
table3gpp->m_uXpr = 8;
|
||||
table3gpp->m_sigXpr = 3;
|
||||
table3gpp->m_perClusterShadowingStd = 4;
|
||||
|
||||
for (uint8_t row = 0; row < 6; row++)
|
||||
{
|
||||
for (uint8_t column = 0; column < 6; column++)
|
||||
{
|
||||
table3gpp->m_sqrtC[row][column] = sqrtC_UMi_LOS[row][column];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Unknown channel condition");
|
||||
}
|
||||
}
|
||||
else if (m_scenario == "V2V-Highway")
|
||||
{
|
||||
if (channelCondition->IsLos ())
|
||||
{
|
||||
table3gpp->m_numOfCluster = 12;
|
||||
table3gpp->m_raysPerCluster = 20;
|
||||
table3gpp->m_uLgDS = -8.3;
|
||||
table3gpp->m_sigLgDS = 0.2;
|
||||
table3gpp->m_uLgASD = 1.4;
|
||||
table3gpp->m_sigLgASD = 0.1;
|
||||
table3gpp->m_uLgASA = 1.4;
|
||||
table3gpp->m_sigLgASA = 0.1;
|
||||
table3gpp->m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73;
|
||||
table3gpp->m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34;
|
||||
table3gpp->m_uLgZSD = -0.1 * log10 (1 + fcGHz) + 0.73;
|
||||
table3gpp->m_sigLgZSD = -0.04 * log10 (1 + fcGHz) + 0.34;
|
||||
table3gpp->m_offsetZOD = 0;
|
||||
table3gpp->m_cDS = 5;
|
||||
table3gpp->m_cASD = 17;
|
||||
table3gpp->m_cASA = 17;
|
||||
table3gpp->m_cZSA = 7;
|
||||
table3gpp->m_uK = 9;
|
||||
table3gpp->m_sigK = 3.5;
|
||||
table3gpp->m_rTau = 3;
|
||||
table3gpp->m_uXpr = 9;
|
||||
table3gpp->m_sigXpr = 3;
|
||||
table3gpp->m_perClusterShadowingStd = 4;
|
||||
|
||||
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 (channelCondition->IsNlosv ())
|
||||
{
|
||||
table3gpp->m_numOfCluster = 19;
|
||||
table3gpp->m_raysPerCluster = 20;
|
||||
table3gpp->m_uLgDS = -8.3;
|
||||
table3gpp->m_sigLgDS = 0.3;
|
||||
table3gpp->m_uLgASD = 1.5;
|
||||
table3gpp->m_sigLgASD = 0.1;
|
||||
table3gpp->m_uLgASA = 1.5;
|
||||
table3gpp->m_sigLgASA = 0.1;
|
||||
table3gpp->m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
|
||||
table3gpp->m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
|
||||
table3gpp->m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
|
||||
table3gpp->m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
|
||||
table3gpp->m_offsetZOD = 0;
|
||||
table3gpp->m_cDS = 11;
|
||||
table3gpp->m_cASD = 22;
|
||||
table3gpp->m_cASA = 22;
|
||||
table3gpp->m_cZSA = 7;
|
||||
table3gpp->m_uK = 0;
|
||||
table3gpp->m_sigK = 4.5;
|
||||
table3gpp->m_rTau = 2.1;
|
||||
table3gpp->m_uXpr = 8.0;
|
||||
table3gpp->m_sigXpr = 3;
|
||||
table3gpp->m_perClusterShadowingStd = 4;
|
||||
|
||||
for (uint8_t row = 0; row < 6; row++)
|
||||
{
|
||||
for (uint8_t column = 0; column < 6; column++)
|
||||
{
|
||||
table3gpp->m_sqrtC[row][column] = sqrtC_UMi_LOS[row][column];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (channelCondition->IsNlos ())
|
||||
{
|
||||
NS_LOG_WARN ("The fast fading parameters for the NLOS condition in the Highway scenario are not defined in TR 37.885, use the ones defined in TDoc R1-1803671 instead");
|
||||
|
||||
table3gpp->m_numOfCluster = 19;
|
||||
table3gpp->m_raysPerCluster = 20;
|
||||
table3gpp->m_uLgDS = -0.3 * log10 (1 + fcGHz) - 7;
|
||||
table3gpp->m_sigLgDS = 0.28;
|
||||
table3gpp->m_uLgASD = -0.08 * log10 (1 + fcGHz) + 1.81;
|
||||
table3gpp->m_sigLgASD = 0.05 * log10 (1 + fcGHz) + 0.3;
|
||||
table3gpp->m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
|
||||
table3gpp->m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
|
||||
table3gpp->m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92,
|
||||
table3gpp->m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
|
||||
table3gpp->m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
|
||||
table3gpp->m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
|
||||
table3gpp->m_offsetZOD = 0;
|
||||
table3gpp->m_cDS = 11;
|
||||
table3gpp->m_cASD = 22;
|
||||
table3gpp->m_cASA = 22;
|
||||
table3gpp->m_cZSA = 7;
|
||||
table3gpp->m_uK = 0; // N/A
|
||||
table3gpp->m_sigK = 0; // N/A
|
||||
table3gpp->m_rTau = 2.1;
|
||||
table3gpp->m_uXpr = 8;
|
||||
table3gpp->m_sigXpr = 3;
|
||||
table3gpp->m_perClusterShadowingStd = 4;
|
||||
|
||||
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
|
||||
{
|
||||
NS_FATAL_ERROR ("unkonw scenarios");
|
||||
@@ -717,25 +944,25 @@ ThreeGppChannelModel::GetThreeGppTable (bool los, bool o2i, double hBS, double h
|
||||
}
|
||||
|
||||
bool
|
||||
ThreeGppChannelModel::ChannelMatrixNeedsUpdate (Ptr<const ThreeGppChannelMatrix> channelMatrix, bool los) const
|
||||
ThreeGppChannelModel::ChannelMatrixNeedsUpdate (Ptr<const ThreeGppChannelMatrix> channelMatrix, Ptr<const ChannelCondition> channelCondition) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
bool update = false;
|
||||
|
||||
// if the los condition is different the channel has to be updated
|
||||
if (channelMatrix->m_los != los)
|
||||
{
|
||||
NS_LOG_DEBUG ("old los condition " << channelMatrix->m_los << " new los condition " << los);
|
||||
update = true;
|
||||
}
|
||||
// if the channel condition is different the channel has to be updated
|
||||
if (!channelMatrix->m_channelCondition->IsEqual (channelCondition))
|
||||
{
|
||||
NS_LOG_DEBUG ("Update the channel condition");
|
||||
update = true;
|
||||
}
|
||||
|
||||
// if the coherence time is over the channel has to be updated
|
||||
if (!m_updatePeriod.IsZero () && Simulator::Now() - channelMatrix->m_generatedTime > m_updatePeriod)
|
||||
{
|
||||
NS_LOG_DEBUG ("Generation time " << channelMatrix->m_generatedTime.As (Time::NS) << " now " << Now ().As (Time::NS));
|
||||
update = true;
|
||||
}
|
||||
if (!m_updatePeriod.IsZero () && Simulator::Now () - channelMatrix->m_generatedTime > m_updatePeriod)
|
||||
{
|
||||
NS_LOG_DEBUG ("Generation time " << channelMatrix->m_generatedTime.As (Time::NS) << " now " << Now ().As (Time::NS));
|
||||
update = true;
|
||||
}
|
||||
|
||||
return update;
|
||||
}
|
||||
@@ -755,8 +982,6 @@ ThreeGppChannelModel::GetChannel (Ptr<const MobilityModel> aMob,
|
||||
|
||||
// retrieve the channel condition
|
||||
Ptr<const ChannelCondition> condition = m_channelConditionModel->GetChannelCondition (aMob, bMob);
|
||||
bool los = (condition->GetLosCondition () == ChannelCondition::LosConditionValue::LOS);
|
||||
bool o2i = false; // TODO include the o2i condition in the channel condition model
|
||||
|
||||
// Check if the channel is present in the map and return it, otherwise
|
||||
// generate a new channel
|
||||
@@ -770,13 +995,13 @@ ThreeGppChannelModel::GetChannel (Ptr<const MobilityModel> aMob,
|
||||
channelMatrix = m_channelMap[channelId];
|
||||
|
||||
// check if it has to be updated
|
||||
update = ChannelMatrixNeedsUpdate (channelMatrix, los);
|
||||
update = ChannelMatrixNeedsUpdate (channelMatrix, condition);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("channel matrix not found");
|
||||
notFound = true;
|
||||
}
|
||||
{
|
||||
NS_LOG_DEBUG ("channel matrix not found");
|
||||
notFound = true;
|
||||
}
|
||||
|
||||
// If the channel is not present in the map or if it has to be updated
|
||||
// generate a new realization
|
||||
@@ -801,18 +1026,18 @@ ThreeGppChannelModel::GetChannel (Ptr<const MobilityModel> aMob,
|
||||
// tx and rx instead
|
||||
Vector locUt = Vector (0.0, 0.0, 0.0);
|
||||
|
||||
channelMatrix = GetNewChannel (locUt, los, o2i, aAntenna, bAntenna, rxAngle, txAngle, distance2D, hBs, hUt);
|
||||
channelMatrix = GetNewChannel (locUt, condition, aAntenna, bAntenna, rxAngle, txAngle, distance2D, hBs, hUt);
|
||||
channelMatrix->m_nodeIds = std::make_pair (aMob->GetObject<Node> ()->GetId (), bMob->GetObject<Node> ()->GetId ());
|
||||
|
||||
// store or replace the channel matrix in the channel map
|
||||
m_channelMap[channelId] = channelMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
return channelMatrix;
|
||||
}
|
||||
|
||||
Ptr<ThreeGppChannelModel::ThreeGppChannelMatrix>
|
||||
ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
ThreeGppChannelModel::GetNewChannel (Vector locUT, Ptr<const ChannelCondition> channelCondition,
|
||||
Ptr<const ThreeGppAntennaArrayModel> sAntenna,
|
||||
Ptr<const ThreeGppAntennaArrayModel> uAntenna,
|
||||
Angles &uAngle, Angles &sAngle,
|
||||
@@ -823,7 +1048,7 @@ ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
NS_ASSERT_MSG (m_frequency > 0.0, "Set the operating frequency first!");
|
||||
|
||||
// get the 3GPP parameters
|
||||
Ptr<const ParamsTable> table3gpp = GetThreeGppTable (los, o2i, hBS, hUT, dis2D);
|
||||
Ptr<const ParamsTable> table3gpp = GetThreeGppTable (channelCondition, hBS, hUT, dis2D);
|
||||
|
||||
// get the number of clusters and the number of rays per cluster
|
||||
uint8_t numOfCluster = table3gpp->m_numOfCluster;
|
||||
@@ -831,13 +1056,15 @@ ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
|
||||
// create a channel matrix instance
|
||||
Ptr<ThreeGppChannelMatrix> channelParams = Create<ThreeGppChannelMatrix> ();
|
||||
channelParams->m_los = los; // set the LOS condition
|
||||
channelParams->m_o2i = o2i; // set the O2I condition
|
||||
channelParams->m_channelCondition = channelCondition; // set the channel condition
|
||||
channelParams->m_generatedTime = Simulator::Now ();
|
||||
|
||||
// compute the 3D distance using eq. 7.4-1
|
||||
double dis3D = std::sqrt (dis2D * dis2D + (hBS - hUT) * (hBS - hUT));
|
||||
|
||||
bool los = channelCondition->IsLos ();
|
||||
bool o2i = channelCondition->IsO2i ();
|
||||
|
||||
//Step 4: Generate large scale parameters. All LSPS are uncorrelated.
|
||||
DoubleVector LSPsIndep, LSPs;
|
||||
uint8_t paramNum;
|
||||
@@ -900,7 +1127,7 @@ ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
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)
|
||||
double tau = -1 * table3gpp->m_rTau * DS * log (m_uniformRv->GetValue (0,1)); //(7.5-1)
|
||||
if (minTau > tau)
|
||||
{
|
||||
minTau = tau;
|
||||
@@ -980,7 +1207,7 @@ ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERT(clusterPower.size () < UINT8_MAX);
|
||||
NS_ASSERT (clusterPower.size () < UINT8_MAX);
|
||||
uint8_t numReducedCluster = clusterPower.size ();
|
||||
|
||||
channelParams->m_numCluster = numReducedCluster;
|
||||
@@ -1001,41 +1228,41 @@ ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
//Not sure why the other cases are in Table 7.5-2.
|
||||
switch (numOfCluster) // Table 7.5-2
|
||||
{
|
||||
case 4:
|
||||
C_NLOS = 0.779;
|
||||
break;
|
||||
case 5:
|
||||
C_NLOS = 0.860;
|
||||
break;
|
||||
case 8:
|
||||
C_NLOS = 1.018;
|
||||
break;
|
||||
case 10:
|
||||
C_NLOS = 1.090;
|
||||
break;
|
||||
case 11:
|
||||
C_NLOS = 1.123;
|
||||
break;
|
||||
case 12:
|
||||
C_NLOS = 1.146;
|
||||
break;
|
||||
case 14:
|
||||
C_NLOS = 1.190;
|
||||
break;
|
||||
case 15:
|
||||
C_NLOS = 1.221;
|
||||
break;
|
||||
case 16:
|
||||
C_NLOS = 1.226;
|
||||
break;
|
||||
case 19:
|
||||
C_NLOS = 1.273;
|
||||
break;
|
||||
case 20:
|
||||
C_NLOS = 1.289;
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Invalid cluster number");
|
||||
case 4:
|
||||
C_NLOS = 0.779;
|
||||
break;
|
||||
case 5:
|
||||
C_NLOS = 0.860;
|
||||
break;
|
||||
case 8:
|
||||
C_NLOS = 1.018;
|
||||
break;
|
||||
case 10:
|
||||
C_NLOS = 1.090;
|
||||
break;
|
||||
case 11:
|
||||
C_NLOS = 1.123;
|
||||
break;
|
||||
case 12:
|
||||
C_NLOS = 1.146;
|
||||
break;
|
||||
case 14:
|
||||
C_NLOS = 1.190;
|
||||
break;
|
||||
case 15:
|
||||
C_NLOS = 1.221;
|
||||
break;
|
||||
case 16:
|
||||
C_NLOS = 1.226;
|
||||
break;
|
||||
case 19:
|
||||
C_NLOS = 1.273;
|
||||
break;
|
||||
case 20:
|
||||
C_NLOS = 1.289;
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Invalid cluster number");
|
||||
}
|
||||
|
||||
if (los)
|
||||
@@ -1050,29 +1277,29 @@ ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
double C_theta;
|
||||
switch (numOfCluster) //Table 7.5-4
|
||||
{
|
||||
case 8:
|
||||
C_NLOS = 0.889;
|
||||
break;
|
||||
case 10:
|
||||
C_NLOS = 0.957;
|
||||
break;
|
||||
case 11:
|
||||
C_NLOS = 1.031;
|
||||
break;
|
||||
case 12:
|
||||
C_NLOS = 1.104;
|
||||
break;
|
||||
case 15:
|
||||
C_NLOS = 1.1088;
|
||||
break;
|
||||
case 19:
|
||||
C_NLOS = 1.184;
|
||||
break;
|
||||
case 20:
|
||||
C_NLOS = 1.178;
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Invalid cluster number");
|
||||
case 8:
|
||||
C_NLOS = 0.889;
|
||||
break;
|
||||
case 10:
|
||||
C_NLOS = 0.957;
|
||||
break;
|
||||
case 11:
|
||||
C_NLOS = 1.031;
|
||||
break;
|
||||
case 12:
|
||||
C_NLOS = 1.104;
|
||||
break;
|
||||
case 15:
|
||||
C_NLOS = 1.1088;
|
||||
break;
|
||||
case 19:
|
||||
C_NLOS = 1.184;
|
||||
break;
|
||||
case 20:
|
||||
C_NLOS = 1.178;
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Invalid cluster number");
|
||||
}
|
||||
|
||||
if (los)
|
||||
@@ -1089,13 +1316,13 @@ ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
double angle;
|
||||
for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
|
||||
{
|
||||
angle = 2*ASA*sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi; //(7.5-9)
|
||||
angle = 2 * ASA * sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi; //(7.5-9)
|
||||
clusterAoa.push_back (angle);
|
||||
angle = 2*ASD*sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi; //(7.5-9)
|
||||
angle = 2 * ASD * sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi; //(7.5-9)
|
||||
clusterAod.push_back (angle);
|
||||
angle = -1*ZSA*log (clusterPowerForAngles[cIndex] / powerMax) / C_theta; //(7.5-14)
|
||||
angle = -1 * ZSA * log (clusterPowerForAngles[cIndex] / powerMax) / C_theta; //(7.5-14)
|
||||
clusterZoa.push_back (angle);
|
||||
angle = -1*ZSD*log (clusterPowerForAngles[cIndex] / powerMax) / C_theta;
|
||||
angle = -1 * ZSD * log (clusterPowerForAngles[cIndex] / powerMax) / C_theta;
|
||||
clusterZod.push_back (angle);
|
||||
}
|
||||
|
||||
@@ -1220,20 +1447,20 @@ ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
{
|
||||
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");
|
||||
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++)
|
||||
@@ -1258,20 +1485,20 @@ ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
}
|
||||
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");
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1439,38 +1666,38 @@ ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
|
||||
switch (mIndex)
|
||||
{
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 17:
|
||||
case 18:
|
||||
raysSub2 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
|
||||
+exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
|
||||
* exp (std::complex<double> (0, rxPhaseDiff))
|
||||
* exp (std::complex<double> (0, txPhaseDiff));
|
||||
break;
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
raysSub3 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
|
||||
+exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
|
||||
* exp (std::complex<double> (0, rxPhaseDiff))
|
||||
* exp (std::complex<double> (0, txPhaseDiff));
|
||||
break;
|
||||
default: //case 1,2,3,4,5,6,7,8,19,20
|
||||
raysSub1 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
|
||||
+exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
|
||||
* exp (std::complex<double> (0, rxPhaseDiff))
|
||||
* exp (std::complex<double> (0, txPhaseDiff));
|
||||
break;
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 17:
|
||||
case 18:
|
||||
raysSub2 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
|
||||
+exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
|
||||
* exp (std::complex<double> (0, rxPhaseDiff))
|
||||
* exp (std::complex<double> (0, txPhaseDiff));
|
||||
break;
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
raysSub3 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
|
||||
+exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
|
||||
* exp (std::complex<double> (0, rxPhaseDiff))
|
||||
* exp (std::complex<double> (0, txPhaseDiff));
|
||||
break;
|
||||
default: //case 1,2,3,4,5,6,7,8,19,20
|
||||
raysSub1 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 / k) * rxFieldPatternTheta * txFieldPatternPhi +
|
||||
+exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 / k) * rxFieldPatternPhi * txFieldPatternTheta +
|
||||
+exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
|
||||
* exp (std::complex<double> (0, rxPhaseDiff))
|
||||
* exp (std::complex<double> (0, txPhaseDiff));
|
||||
break;
|
||||
}
|
||||
}
|
||||
raysSub1 *= sqrt (clusterPower[nIndex] / raysPerCluster);
|
||||
@@ -1499,9 +1726,9 @@ ThreeGppChannelModel::GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
double lambda = 3e8 / m_frequency; // the wavelength of the carrier frequency
|
||||
|
||||
ray = (rxFieldPatternTheta * txFieldPatternTheta - rxFieldPatternPhi * txFieldPatternPhi)
|
||||
* exp (std::complex<double> (0, - 2 * M_PI * dis3D / lambda))
|
||||
* exp (std::complex<double> (0, rxPhaseDiff))
|
||||
* exp (std::complex<double> (0, txPhaseDiff));
|
||||
* exp (std::complex<double> (0, -2 * M_PI * dis3D / lambda))
|
||||
* exp (std::complex<double> (0, rxPhaseDiff))
|
||||
* exp (std::complex<double> (0, txPhaseDiff));
|
||||
|
||||
double K_linear = pow (10,K_factor / 10);
|
||||
// the LOS path should be attenuated if blockage is enabled.
|
||||
@@ -1663,7 +1890,7 @@ ThreeGppChannelModel::CalcAttenuationOfBlockage (Ptr<ThreeGppChannelModel::Three
|
||||
}
|
||||
else
|
||||
{
|
||||
if (params->m_o2i) // outdoor to indoor
|
||||
if (params->m_channelCondition->IsO2i ()) // outdoor to indoor
|
||||
{
|
||||
corrDis = 5;
|
||||
}
|
||||
@@ -1813,7 +2040,7 @@ ThreeGppChannelModel::CalcAttenuationOfBlockage (Ptr<ThreeGppChannelModel::Three
|
||||
void
|
||||
ThreeGppChannelModel::Shuffle (double * first, double * last) const
|
||||
{
|
||||
for (auto i = (last-first) - 1 ; i > 0; --i)
|
||||
for (auto i = (last - first) - 1; i > 0; --i)
|
||||
{
|
||||
std::swap (first[i], first[m_uniformRvShuffle->GetInteger (0, i)]);
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
* \return the number of stream indices assigned by this model
|
||||
*/
|
||||
int64_t AssignStreams (int64_t stream);
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Shuffle the elements of a simple sequence container of type double
|
||||
@@ -141,7 +141,7 @@ private:
|
||||
*/
|
||||
struct ThreeGppChannelMatrix : public MatrixBasedChannelModel::ChannelMatrix
|
||||
{
|
||||
bool m_los; //!< true if LOS, false if NLOS
|
||||
Ptr<const ChannelCondition> m_channelCondition; //!< the channel condition
|
||||
|
||||
// TODO these are not currently used, they have to be correctly set when including the spatial consistent update procedure
|
||||
/*The following parameters are stored for spatial consistent updating. The notation is
|
||||
@@ -154,7 +154,6 @@ private:
|
||||
double m_K; //!< K factor
|
||||
uint8_t m_numCluster; //!< reduced cluster number;
|
||||
MatrixBasedChannelModel::Double3DVector m_clusterPhase; //!< the initial random phases
|
||||
bool m_o2i; //!< true if O2I
|
||||
Vector m_speed; //!< velocity
|
||||
double m_dis2D; //!< 2D distance between tx and rx
|
||||
double m_dis3D; //!< 3D distance between tx and rx
|
||||
@@ -195,21 +194,19 @@ private:
|
||||
|
||||
/**
|
||||
* Get the parameters needed to apply the channel generation procedure
|
||||
* \param los the LOS/NLOS condition
|
||||
* \param o2i whether if it is an outdoor to indoor transmission
|
||||
* \param channelCondition the channel condition
|
||||
* \param hBS the height of the BS
|
||||
* \param hUT the height of the UT
|
||||
* \param distance2D the 2D distance between tx and rx
|
||||
* \return the parameters table
|
||||
*/
|
||||
Ptr<const ParamsTable> GetThreeGppTable (bool los, bool o2i, double hBS, double hUT, double distance2D) const;
|
||||
virtual Ptr<const ParamsTable> GetThreeGppTable (Ptr<const ChannelCondition> channelCondition, double hBS, double hUT, double distance2D) const;
|
||||
|
||||
/**
|
||||
* Compute the channel matrix between two devices using the procedure
|
||||
* described in 3GPP TR 38.901
|
||||
* \param locUT the location of the UT
|
||||
* \param los the LOS/NLOS condition
|
||||
* \param o2i whether if it is an outdoor to indoor transmission
|
||||
* \param channelCondition the channel condition
|
||||
* \param sAntenna the s node antenna array
|
||||
* \param uAntenna the u node antenna array
|
||||
* \param uAngle the u node angle
|
||||
@@ -219,7 +216,7 @@ private:
|
||||
* \param hUT the height of the UT
|
||||
* \return the channel realization
|
||||
*/
|
||||
Ptr<ThreeGppChannelMatrix> GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
Ptr<ThreeGppChannelMatrix> GetNewChannel (Vector locUT, Ptr<const ChannelCondition> channelCondition,
|
||||
Ptr<const ThreeGppAntennaArrayModel> sAntenna,
|
||||
Ptr<const ThreeGppAntennaArrayModel> uAntenna,
|
||||
Angles &uAngle, Angles &sAngle,
|
||||
@@ -239,10 +236,10 @@ private:
|
||||
/**
|
||||
* Check if the channel matrix has to be updated
|
||||
* \param channelMatrix channel matrix
|
||||
* \param isLos the current los condition
|
||||
* \param channelCondition the channel condition
|
||||
* \return true if the channel matrix has to be updated, false otherwise
|
||||
*/
|
||||
bool ChannelMatrixNeedsUpdate (Ptr<const ThreeGppChannelMatrix> channelMatrix, bool isLos) const;
|
||||
bool ChannelMatrixNeedsUpdate (Ptr<const ThreeGppChannelMatrix> channelMatrix, Ptr<const ChannelCondition> channelCondition) const;
|
||||
|
||||
std::unordered_map<uint32_t, Ptr<ThreeGppChannelMatrix> > m_channelMap; //!< map containing the channel realizations
|
||||
Time m_updatePeriod; //!< the channel update period
|
||||
|
||||
@@ -41,6 +41,7 @@ NS_OBJECT_ENSURE_REGISTERED (ThreeGppSpectrumPropagationLossModel);
|
||||
ThreeGppSpectrumPropagationLossModel::ThreeGppSpectrumPropagationLossModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_uniformRv = CreateObject<UniformRandomVariable> ();
|
||||
}
|
||||
|
||||
ThreeGppSpectrumPropagationLossModel::~ThreeGppSpectrumPropagationLossModel ()
|
||||
@@ -69,7 +70,14 @@ ThreeGppSpectrumPropagationLossModel::GetTypeId (void)
|
||||
StringValue("ns3::ThreeGppChannelModel"),
|
||||
MakePointerAccessor (&ThreeGppSpectrumPropagationLossModel::SetChannelModel,
|
||||
&ThreeGppSpectrumPropagationLossModel::GetChannelModel),
|
||||
MakePointerChecker<MatrixBasedChannelModel> ())
|
||||
MakePointerChecker<MatrixBasedChannelModel> ())
|
||||
.AddAttribute ("vScatt",
|
||||
"Maximum speed of the vehicle in the layout (see 3GPP TR 37.885 v15.3.0, Sec. 6.2.3)."
|
||||
"Used to compute the additional contribution for the Doppler of"
|
||||
"delayed (reflected) paths",
|
||||
DoubleValue (0.0),
|
||||
MakeDoubleAccessor (&ThreeGppSpectrumPropagationLossModel::m_vScatt),
|
||||
MakeDoubleChecker<double> (0.0))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
@@ -166,15 +174,32 @@ ThreeGppSpectrumPropagationLossModel::CalcBeamformingGain (Ptr<SpectrumValue> tx
|
||||
ThreeGppAntennaArrayModel::ComplexVector doppler;
|
||||
for (uint8_t cIndex = 0; cIndex < numCluster; cIndex++)
|
||||
{
|
||||
// Compute alpha and D as described in 3GPP TR 37.885 v15.3.0, Sec. 6.2.3
|
||||
// These terms account for an additional Doppler contribution due to the
|
||||
// presence of moving objects in the sorrounding environment, such as in
|
||||
// vehicular scenarios.
|
||||
// This contribution is applied only to the delayed (reflected) paths and
|
||||
// must be properly configured by setting the value of
|
||||
// m_vScatt, which is defined as "maximum speed of the vehicle in the
|
||||
// layout".
|
||||
// By default, m_vScatt is set to 0, so there is no additional Doppler
|
||||
// contribution.
|
||||
double alpha = 0;
|
||||
double D = 0;
|
||||
if (cIndex != 0)
|
||||
{
|
||||
alpha = m_uniformRv->GetValue (-1, 1);
|
||||
D = m_uniformRv->GetValue (-m_vScatt, m_vScatt);
|
||||
}
|
||||
|
||||
//cluster angle angle[direction][n],where, direction = 0(aoa), 1(zoa).
|
||||
// TODO should I include the "alfa" term for the Doppler of delayed paths?
|
||||
double temp_doppler = 2 * M_PI * ((sin (params->m_angle[MatrixBasedChannelModel::ZOA_INDEX][cIndex] * M_PI / 180) * cos (params->m_angle[MatrixBasedChannelModel::AOA_INDEX][cIndex] * M_PI / 180) * uSpeed.x
|
||||
+ sin (params->m_angle[MatrixBasedChannelModel::ZOA_INDEX][cIndex] * M_PI / 180) * sin (params->m_angle[MatrixBasedChannelModel::AOA_INDEX][cIndex] * M_PI / 180) * uSpeed.y
|
||||
+ cos (params->m_angle[MatrixBasedChannelModel::ZOA_INDEX][cIndex] * M_PI / 180) * uSpeed.z)
|
||||
+ (sin (params->m_angle[MatrixBasedChannelModel::ZOD_INDEX][cIndex] * M_PI / 180) * cos (params->m_angle[MatrixBasedChannelModel::AOD_INDEX][cIndex] * M_PI / 180) * sSpeed.x
|
||||
+ sin (params->m_angle[MatrixBasedChannelModel::ZOD_INDEX][cIndex] * M_PI / 180) * sin (params->m_angle[MatrixBasedChannelModel::AOD_INDEX][cIndex] * M_PI / 180) * sSpeed.y
|
||||
+ cos (params->m_angle[MatrixBasedChannelModel::ZOD_INDEX][cIndex] * M_PI / 180) * sSpeed.z))
|
||||
* slotTime * GetFrequency () / 3e8;
|
||||
+ cos (params->m_angle[MatrixBasedChannelModel::ZOD_INDEX][cIndex] * M_PI / 180) * sSpeed.z) + 2 * alpha * D)
|
||||
* slotTime * GetFrequency () / 3e8;
|
||||
doppler.push_back (exp (std::complex<double> (0, temp_doppler)));
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include "ns3/matrix-based-channel-model.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -190,6 +191,11 @@ private:
|
||||
std::unordered_map <uint32_t, Ptr<const ThreeGppAntennaArrayModel> > m_deviceAntennaMap; //!< map containig the <node, antenna> associations
|
||||
mutable std::unordered_map < uint32_t, Ptr<const LongTerm> > m_longTermMap; //!< map containing the long term components
|
||||
Ptr<MatrixBasedChannelModel> m_channelModel; //!< the model to generate the channel matrix
|
||||
|
||||
// Variable used to compute the additional Doppler contribution for the delayed
|
||||
// (reflected) paths, as described in 3GPP TR 37.885 v15.3.0, Sec. 6.2.3.
|
||||
double m_vScatt; //!< value used to compute the additional Doppler contribution for the delayed paths
|
||||
Ptr<UniformRandomVariable> m_uniformRv; //!< uniform random variable, used to compute the additional Doppler contribution
|
||||
};
|
||||
} // namespace ns3
|
||||
|
||||
|
||||
Reference in New Issue
Block a user