Integration of the 3GPP TR 38.901 fast fading model (GSoC 2019) (2/2)
Close !90
This commit is contained in:
committed by
Natale Patriciello
parent
b98955f20a
commit
b4f5695e05
660
RELEASE_NOTES
660
RELEASE_NOTES
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,8 @@ Overview
|
||||
The Antenna module provides:
|
||||
|
||||
#. a new base class (AntennaModel) that provides an interface for the modeling of the radiation pattern of an antenna;
|
||||
#. a set of classes derived from this base class that each models the radiation pattern of different types of antennas.
|
||||
#. a set of classes derived from this base class that each models the radiation pattern of different types of antennas;
|
||||
#. the class ThreeGppAntennaArrayModel, which implements the antenna model described in 3GPP TR 38.901
|
||||
|
||||
|
||||
------------
|
||||
@@ -25,8 +26,8 @@ is obtained by translating the Cartesian coordinate system used by the
|
||||
ns-3 MobilityModel into the new origin :math:`o` which is the location
|
||||
of the antenna, and then transforming the coordinates of every generic
|
||||
point :math:`p` of the space from Cartesian coordinates
|
||||
:math:`(x,y,z)` into spherical coordinates
|
||||
:math:`(r, \theta,\phi)`.
|
||||
:math:`(x,y,z)` into spherical coordinates
|
||||
:math:`(r, \theta,\phi)`.
|
||||
The antenna model neglects the radial component :math:`r`, and
|
||||
only considers the angle components :math:`(\theta, \phi)`. An antenna
|
||||
radiation pattern is then expressed as a mathematical function
|
||||
@@ -36,15 +37,15 @@ transmission/reception. All angles are expressed in radians.
|
||||
|
||||
|
||||
.. _fig-antenna-coordinate-system:
|
||||
|
||||
|
||||
.. figure:: figures/antenna-coordinate-system.*
|
||||
:align: center
|
||||
|
||||
Coordinate system of the AntennaModel
|
||||
|
||||
---------------
|
||||
Provided models
|
||||
---------------
|
||||
---------------------
|
||||
Single antenna models
|
||||
---------------------
|
||||
|
||||
In this section we describe the antenna radiation pattern models that
|
||||
are included within the antenna module.
|
||||
@@ -65,19 +66,19 @@ This is the cosine model described in [Chunjian]_: the antenna gain is
|
||||
determined as:
|
||||
|
||||
.. math::
|
||||
|
||||
|
||||
g(\phi, \theta) = \cos^{n} \left(\frac{\phi - \phi_{0}}{2} \right)
|
||||
|
||||
where :math:`\phi_{0}` is the azimuthal orientation of the antenna
|
||||
(i.e., its direction of maximum gain) and the exponential
|
||||
|
||||
.. math::
|
||||
|
||||
|
||||
n = -\frac{3}{20 \log_{10} \left( \cos \frac{\phi_{3dB}}{4} \right)}
|
||||
|
||||
determines the desired 3dB beamwidth :math:`\phi_{3dB}`. Note that
|
||||
this radiation pattern is independent of the inclination angle
|
||||
:math:`\theta`.
|
||||
:math:`\theta`.
|
||||
|
||||
A major difference between the model of [Chunjian]_ and the one
|
||||
implemented in the class CosineAntennaModel is that only the element
|
||||
@@ -97,18 +98,35 @@ ParabolicAntennaModel
|
||||
This model is based on the parabolic approximation of the main lobe radiation pattern. It is often used in the context of cellular system to model the radiation pattern of a cell sector, see for instance [R4-092042a]_ and [Calcev]_. The antenna gain in dB is determined as:
|
||||
|
||||
.. math::
|
||||
|
||||
|
||||
g_{dB}(\phi, \theta) = -\min \left( 12 \left(\frac{\phi - \phi_{0}}{\phi_{3dB}} \right)^2, A_{max} \right)
|
||||
|
||||
where :math:`\phi_{0}` is the azimuthal orientation of the antenna
|
||||
(i.e., its direction of maximum gain), :math:`\phi_{3dB}` is its 3 dB
|
||||
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`.
|
||||
|
||||
|
||||
:math:`\theta`.
|
||||
|
||||
-------------------------
|
||||
ThreeGppAntennaArrayModel
|
||||
-------------------------
|
||||
|
||||
The class ThreeGppAntennaArrayModel implements the antenna model described in
|
||||
3GPP TR 38.901 [38901]_, which is used by the classes ThreeGppSpectrumPropagationLossModel
|
||||
and ThreeGppChannelModel.
|
||||
Each instance of this class models an isotropic rectangular antenna array with
|
||||
NxM elements, where N is the number of rows and M is the number of columns,
|
||||
configurable through the attributes "NumRows" and "NumColumns".
|
||||
The radiation pattern of the antenna elements follows the model specified in
|
||||
Sec. 7.3 of 3GPP TR 38.901; only vertical polarization is considered (i.e.,
|
||||
:math:`{\zeta = 0}`).
|
||||
The directional gain of the antenna elements can be configured through the
|
||||
attribute "ElementGain" (see formula 2.34 in [Mailloux]_ to choose a proper value).
|
||||
By default, the array is orthogonal to the x-axis, pointing towards the positive
|
||||
direction, but the orientation can be changed through the attributes "BearingAngle",
|
||||
which adjusts the azimuth angle, and "DowntiltAngle", which adjusts the elevation angle.
|
||||
The spacing between the horizontal and vertical elements can be configured through
|
||||
the attributes "AntennaHorizontalSpacing" and "AntennaVerticalSpacing".
|
||||
|
||||
.. [Balanis] C.A. Balanis, "Antenna Theory - Analysis and Design", Wiley, 2nd Ed.
|
||||
|
||||
@@ -118,10 +136,11 @@ antenna. Note that this radiation pattern is independent of the inclination angl
|
||||
|
||||
.. [Calcev] George Calcev and Matt Dillon, "Antenna Tilt Control in
|
||||
CDMA Networks", in Proc. of the 2nd Annual International Wireless
|
||||
Internet Conference (WICON), 2006
|
||||
Internet Conference (WICON), 2006
|
||||
|
||||
.. [R4-092042a] 3GPP TSG RAN WG4 (Radio) Meeting #51, R4-092042, Simulation
|
||||
assumptions and parameters for FDD HeNB RF requirements.
|
||||
|
||||
.. [38901] 3GPP. 2018. TR 38.901, Study on channel model for frequencies from 0.5 to 100 GHz, V15.0.0. (2018-06).
|
||||
|
||||
|
||||
.. [Mailloux] Robert J. Mailloux, "Phased Array Antenna Handbook", Artech House, 2nd Ed.
|
||||
|
||||
223
src/antenna/model/three-gpp-antenna-array-model.cc
Normal file
223
src/antenna/model/three-gpp-antenna-array-model.cc
Normal file
@@ -0,0 +1,223 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2019 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-antenna-array-model.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/boolean.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ThreeGppAntennaArrayModel");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ThreeGppAntennaArrayModel);
|
||||
|
||||
ThreeGppAntennaArrayModel::ThreeGppAntennaArrayModel (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_isOmniTx = false;
|
||||
}
|
||||
|
||||
ThreeGppAntennaArrayModel::~ThreeGppAntennaArrayModel (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
TypeId
|
||||
ThreeGppAntennaArrayModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::ThreeGppAntennaArrayModel")
|
||||
.SetParent<Object> ()
|
||||
.AddConstructor<ThreeGppAntennaArrayModel> ()
|
||||
.AddAttribute ("AntennaHorizontalSpacing",
|
||||
"Horizontal spacing between antenna elements, in multiples of wave length",
|
||||
DoubleValue (0.5),
|
||||
MakeDoubleAccessor (&ThreeGppAntennaArrayModel::m_disH),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("AntennaVerticalSpacing",
|
||||
"Vertical spacing between antenna elements, in multiples of wave length",
|
||||
DoubleValue (0.5),
|
||||
MakeDoubleAccessor (&ThreeGppAntennaArrayModel::m_disV),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("NumColumns",
|
||||
"Horizontal size of the array",
|
||||
UintegerValue (4),
|
||||
MakeUintegerAccessor (&ThreeGppAntennaArrayModel::m_numColumns),
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
.AddAttribute ("NumRows",
|
||||
"Vertical size of the array",
|
||||
UintegerValue (4),
|
||||
MakeUintegerAccessor (&ThreeGppAntennaArrayModel::m_numRows),
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
.AddAttribute ("BearingAngle",
|
||||
"The bearing angle in radians",
|
||||
DoubleValue (0.0),
|
||||
MakeDoubleAccessor (&ThreeGppAntennaArrayModel::m_alpha),
|
||||
MakeDoubleChecker<double> (-M_PI, M_PI))
|
||||
.AddAttribute ("DowntiltAngle",
|
||||
"The downtilt angle in radians",
|
||||
DoubleValue (0.0),
|
||||
MakeDoubleAccessor (&ThreeGppAntennaArrayModel::m_beta),
|
||||
MakeDoubleChecker<double> (0, M_PI))
|
||||
.AddAttribute ("ElementGain",
|
||||
"Directional gain of an antenna element in dBi",
|
||||
DoubleValue (4.97),
|
||||
MakeDoubleAccessor (&ThreeGppAntennaArrayModel::m_gE),
|
||||
MakeDoubleChecker<double> (0, 8))
|
||||
.AddAttribute ("IsotropicElements",
|
||||
"If true, use an isotropic radiation pattern (for testing purposes)",
|
||||
BooleanValue (false),
|
||||
MakeBooleanAccessor (&ThreeGppAntennaArrayModel::m_isIsotropic),
|
||||
MakeBooleanChecker ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
bool
|
||||
ThreeGppAntennaArrayModel::IsOmniTx (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_isOmniTx;
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppAntennaArrayModel::ChangeToOmniTx (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_isOmniTx = true;
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppAntennaArrayModel::SetBeamformingVector (const ComplexVector &beamformingVector)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_isOmniTx = false;
|
||||
m_beamformingVector = beamformingVector;
|
||||
}
|
||||
|
||||
const ThreeGppAntennaArrayModel::ComplexVector &
|
||||
ThreeGppAntennaArrayModel::GetBeamformingVector(void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_beamformingVector;
|
||||
}
|
||||
|
||||
std::pair<double, double>
|
||||
ThreeGppAntennaArrayModel::GetElementFieldPattern (Angles a) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// normalize phi (if needed)
|
||||
while (a.phi >= M_PI)
|
||||
{
|
||||
a.phi -= 2 * M_PI;
|
||||
}
|
||||
while (a.phi < -M_PI)
|
||||
{
|
||||
a.phi += 2 * M_PI;
|
||||
}
|
||||
|
||||
NS_ASSERT_MSG (a.theta >= 0 && a.theta <= M_PI, "The vertical angle should be between 0 and M_PI");
|
||||
NS_ASSERT_MSG (a.phi >= -M_PI && a.phi <= M_PI, "The horizontal angle should be between -M_PI and M_PI");
|
||||
|
||||
// convert the theta and phi angles from GCS to LCS using eq. 7.1-7 and 7.1-8 in 3GPP TR 38.901
|
||||
// NOTE we assume a fixed slant angle of 0 degrees
|
||||
double thetaPrime = std::acos (cos (m_beta)*cos (a.theta) + sin (m_beta)*cos (a.phi-m_alpha)*sin (a.theta));
|
||||
double phiPrime = std::arg (std::complex<double> (cos (m_beta)*sin (a.theta)*cos (a.phi-m_alpha) - sin (m_beta)*cos (a.theta), sin (a.phi-m_alpha)*sin (a.theta)));
|
||||
NS_LOG_DEBUG (a.theta << " " << thetaPrime << " " << a.phi << " " << phiPrime);
|
||||
|
||||
double aPrimeDb = GetRadiationPattern (thetaPrime, phiPrime);
|
||||
double aPrime = pow (10, aPrimeDb / 10); // convert to linear
|
||||
|
||||
// compute psi using eq. 7.1-15 in 3GPP TR 38.901
|
||||
double psi = std::arg (std::complex<double> (cos (m_beta) * sin (a.theta) - sin (m_beta) * cos (a.theta)* cos (a.phi - m_alpha), sin (m_beta)* sin (a.phi-m_alpha)));
|
||||
NS_LOG_DEBUG ("psi " << psi);
|
||||
|
||||
// compute the antenna element field pattern in the vertical polarization using
|
||||
// eq. 7.3-4 in 3GPP TR 38.901
|
||||
// NOTE we assume vertical polarization, hence the field pattern in the
|
||||
// vertical polarization is 0
|
||||
double fieldThetaPrime = std::sqrt (aPrime);
|
||||
|
||||
// convert the antenna element field pattern to GCS using eq. 7.1-11
|
||||
// in 3GPP TR 38.901
|
||||
double fieldTheta = cos (psi) * fieldThetaPrime;
|
||||
double fieldPhi = sin (psi) * fieldThetaPrime;
|
||||
NS_LOG_DEBUG (a.phi/M_PI*180 << " " << a.theta/M_PI*180 << " " << fieldTheta*fieldTheta + fieldPhi*fieldPhi);
|
||||
|
||||
return std::make_pair (fieldPhi, fieldTheta);
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppAntennaArrayModel::GetRadiationPattern (double thetaRadian, double phiRadian) const
|
||||
{
|
||||
if (m_isIsotropic)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// convert the angles in degrees
|
||||
double thetaDeg = thetaRadian * 180 / M_PI;
|
||||
double phiDeg = phiRadian * 180 / M_PI;
|
||||
NS_ASSERT_MSG (thetaDeg >= 0 && thetaDeg <= 180, "the vertical angle should be the range of [0,180]");
|
||||
NS_ASSERT_MSG (phiDeg >= -180 && phiDeg <= 180, "the horizontal angle should be the range of [-180,180]");
|
||||
|
||||
// compute the radiation power pattern using equations in table 7.3-1 in
|
||||
// 3GPP TR 38.901
|
||||
double A_M = 30; // front-back ratio expressed in dB
|
||||
double SLA = 30; // side-lobe level limit expressed in dB
|
||||
|
||||
double A_v = -1 * std::min (SLA,12 * pow ((thetaDeg - 90) / 65,2)); // vertical cut of the radiation power pattern (dB)
|
||||
double A_h = -1 * std::min (A_M,12 * pow (phiDeg / 65,2)); // horizontal cut of the radiation power pattern (dB)
|
||||
|
||||
double A = m_gE - 1 * std::min (A_M,- A_v - A_h); // 3D radiation power pattern (dB)
|
||||
|
||||
return A; // 3D radiation power pattern in dB
|
||||
}
|
||||
|
||||
Vector
|
||||
ThreeGppAntennaArrayModel::GetElementLocation (uint64_t index) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// compute the element coordinates in the LCS
|
||||
// assume the left bottom corner is (0,0,0), and the rectangular antenna array is on the y-z plane.
|
||||
double xPrime = 0;
|
||||
double yPrime = m_disH * (index % m_numColumns);
|
||||
double zPrime = m_disV * floor (index / m_numColumns);
|
||||
|
||||
// convert the coordinates to the GCS using the rotation matrix 7.1-4 in 3GPP
|
||||
// TR 38.901
|
||||
Vector loc;
|
||||
loc.x = cos(m_alpha)*cos (m_beta)*xPrime - sin (m_alpha)*yPrime + cos (m_alpha)*sin (m_beta)*zPrime;
|
||||
loc.y = sin (m_alpha)*cos(m_beta)*xPrime + cos (m_alpha)*yPrime + sin (m_alpha)*sin (m_beta)*zPrime;
|
||||
loc.z = -sin (m_beta)*xPrime+cos(m_beta)*zPrime;
|
||||
return loc;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
ThreeGppAntennaArrayModel::GetNumberOfElements (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_numRows * m_numColumns;
|
||||
}
|
||||
|
||||
} /* namespace ns3 */
|
||||
124
src/antenna/model/three-gpp-antenna-array-model.h
Normal file
124
src/antenna/model/three-gpp-antenna-array-model.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2019 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_ANTENNA_ARRAY_MODEL_H_
|
||||
#define THREE_GPP_ANTENNA_ARRAY_MODEL_H_
|
||||
|
||||
#include <ns3/antenna-model.h>
|
||||
#include <complex>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \ingroup antenna
|
||||
*
|
||||
* \brief Class implementing the antenna model defined in 3GPP TR 38.901
|
||||
*/
|
||||
class ThreeGppAntennaArrayModel : public Object
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppAntennaArrayModel (void);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreeGppAntennaArrayModel (void);
|
||||
|
||||
// inherited from Object
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
typedef std::vector<std::complex<double> > ComplexVector; //!< type definition for complex vectors
|
||||
|
||||
/**
|
||||
* Returns the horizontal and vertical components of the antenna element field
|
||||
* pattern at the specified direction
|
||||
* \param a the angle indicating the interested direction
|
||||
* \return a pair in which the first element is the horizontal component
|
||||
* of the field pattern and the second element is the vertical
|
||||
* component of the field pattern
|
||||
*/
|
||||
std::pair<double, double> GetElementFieldPattern (Angles a) const;
|
||||
|
||||
/**
|
||||
* Returns the normalized location of the antenna element
|
||||
* with specified index assuming the left bottom corner is (0,0,0).
|
||||
* \param index index of the antenna element
|
||||
* \return the 3D vector that represents the position of the element
|
||||
*/
|
||||
virtual Vector GetElementLocation (uint64_t index) const;
|
||||
|
||||
/**
|
||||
* Returns the number of antenna elements
|
||||
* \return the number of antenna elements
|
||||
*/
|
||||
virtual uint64_t GetNumberOfElements (void) const;
|
||||
|
||||
/**
|
||||
* Returns true if the antenna is configured for omnidirectional transmissions
|
||||
* \return whether the transmission is set to omni
|
||||
*/
|
||||
bool IsOmniTx (void) const;
|
||||
|
||||
/**
|
||||
* Change the antenna model to omnidirectional (ignoring the beams)
|
||||
*/
|
||||
void ChangeToOmniTx (void);
|
||||
|
||||
/**
|
||||
* Sets the beamforming vector to be used
|
||||
* \param beamformingVector the beamforming vector
|
||||
*/
|
||||
void SetBeamformingVector (const ComplexVector &beamformingVector);
|
||||
|
||||
/**
|
||||
* Returns the beamforming vector that is currently being used
|
||||
* \return the current beamforming vector
|
||||
*/
|
||||
const ComplexVector & GetBeamformingVector (void) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Returns the radiation power pattern of a single antenna element in dB,
|
||||
* generated according to Table 7.3-1 in 3GPP TR 38.901
|
||||
* \param vAngleRadian the vertical angle in radians
|
||||
* \param hAngleRadian the horizontal angle in radians
|
||||
* \return the radiation power pattern in dB
|
||||
*/
|
||||
double GetRadiationPattern (double vAngleRadian, double hAngleRadian) const;
|
||||
|
||||
bool m_isOmniTx; //!< true if the antenna is configured for omni transmissions
|
||||
ComplexVector m_beamformingVector; //!< the beamforming vector in use
|
||||
uint32_t m_numColumns; //!< number of columns
|
||||
uint32_t m_numRows; //!< number of rows
|
||||
double m_disV; //!< antenna spacing in the vertical direction in multiples of wave length
|
||||
double m_disH; //!< antenna spacing in the horizontal direction in multiples of wave length
|
||||
double m_alpha; //!< the bearing angle in radians
|
||||
double m_beta; //!< the downtilt angle in radians
|
||||
double m_gE; //!< directional gain of a single antenna element (dBi)
|
||||
bool m_isIsotropic; //!< if true, antenna elements are isotropic
|
||||
};
|
||||
|
||||
} /* namespace ns3 */
|
||||
|
||||
#endif /* SRC_THREE_GPP_ANTENNA_ARRAY_MODEL_H_ */
|
||||
@@ -10,8 +10,9 @@ def build(bld):
|
||||
'model/isotropic-antenna-model.cc',
|
||||
'model/cosine-antenna-model.cc',
|
||||
'model/parabolic-antenna-model.cc',
|
||||
'model/three-gpp-antenna-array-model.cc',
|
||||
]
|
||||
|
||||
|
||||
module_test = bld.create_ns3_module_test_library('antenna')
|
||||
module_test.source = [
|
||||
'test/test-angles.cc',
|
||||
@@ -20,7 +21,7 @@ def build(bld):
|
||||
'test/test-cosine-antenna.cc',
|
||||
'test/test-parabolic-antenna.cc',
|
||||
]
|
||||
|
||||
|
||||
headers = bld(features='ns3header')
|
||||
headers.module = 'antenna'
|
||||
headers.source = [
|
||||
@@ -29,6 +30,7 @@ def build(bld):
|
||||
'model/isotropic-antenna-model.h',
|
||||
'model/cosine-antenna-model.h',
|
||||
'model/parabolic-antenna-model.h',
|
||||
'model/three-gpp-antenna-array-model.h',
|
||||
]
|
||||
|
||||
bld.ns3_python_bindings()
|
||||
|
||||
@@ -17,15 +17,15 @@ Spectrum Module
|
||||
|
||||
|
||||
|
||||
The Spectrum module aims at providing support for modeling the frequency-dependent
|
||||
aspects of communications in |ns3|.
|
||||
The Spectrum module aims at providing support for modeling the frequency-dependent
|
||||
aspects of communications in |ns3|.
|
||||
The model was first introduced in
|
||||
[Baldo2009Spectrum]_, and has been enhanced and refined over the years.
|
||||
[Baldo2009Spectrum]_, and has been enhanced and refined over the years.
|
||||
|
||||
|
||||
|
||||
.. _fig-spectrum-analyzer-example:
|
||||
|
||||
|
||||
.. figure:: figures/spectrum-analyzer-example.*
|
||||
:align: center
|
||||
|
||||
@@ -39,7 +39,7 @@ Model Description
|
||||
|
||||
The module provides:
|
||||
|
||||
* a set of classes for modeling signals and
|
||||
* a set of classes for modeling signals and
|
||||
|
||||
* a Channel/PHY interface based on a power spectral density
|
||||
signal representation that is technology-independent
|
||||
@@ -70,7 +70,7 @@ information for a signal being transmitted/received by PHY devices:
|
||||
* the duration of the signal
|
||||
|
||||
* its Power Spectral Density (PSD) of the signal, which is assumed to be constant for
|
||||
the duration of the signal.
|
||||
the duration of the signal.
|
||||
|
||||
The PSD is represented as a set of discrete scalar values each
|
||||
corresponding to a certain subband in frequency. The set of frequency subbands
|
||||
@@ -95,7 +95,7 @@ that inherits from ``SpectrumSignalParameters`` and extends it with
|
||||
any technology-specific information that is needed. This design
|
||||
is intended to model the fact that in the real world we have signals
|
||||
of different technologies being simultaneously transmitted and
|
||||
received over the air.
|
||||
received over the air.
|
||||
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ reception of signals over the medium. The way this interaction works is depicted
|
||||
|
||||
|
||||
.. _fig-spectrum-channel-phy-interface:
|
||||
|
||||
|
||||
.. figure:: figures/spectrum-channel-phy-interface.*
|
||||
:align: center
|
||||
|
||||
@@ -127,7 +127,7 @@ both provide this functionality:
|
||||
|
||||
- you can plug models based on ``PropagationLossModel`` on these
|
||||
channels. Only linear models (where the loss value does not
|
||||
depend on the transmission power) can be used.
|
||||
depend on the transmission power) can be used.
|
||||
These models are single-frequency in the sense that the loss value is
|
||||
applied equally to all components of the power spectral density.
|
||||
|
||||
@@ -144,7 +144,7 @@ both provide this functionality:
|
||||
|
||||
``SingleModelSpectrumChannel`` and ``MultiModelSpectrumChannel`` are
|
||||
quite similar, the main difference is that
|
||||
``MultiModelSpectrumChannel`` allows to use different
|
||||
``MultiModelSpectrumChannel`` allows to use different
|
||||
``SpectrumModel`` instances with the same channel instance, by
|
||||
automatically taking care of the conversion of PSDs among the
|
||||
different models.
|
||||
@@ -178,23 +178,23 @@ of the available implementations:
|
||||
|
||||
* ``AlohaNoackNetDevice``: a minimal NetDevice that allows to send
|
||||
packets over ``HalfDuplexIdealPhy`` (or other PHY model based on
|
||||
the ``GenericPhy`` interface).
|
||||
the ``GenericPhy`` interface).
|
||||
|
||||
* ``SpectrumAnalyzer``, ``WaveformGenerator`` and ``MicrowaveOven`` are examples of PHY
|
||||
models other than communication devices - the names should be
|
||||
self-explaining.
|
||||
self-explaining.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
.. [Baldo2009Spectrum] N. Baldo and M. Miozzo, "Spectrum-aware Channel and PHY layer modeling for ns3",
|
||||
.. [Baldo2009Spectrum] N. Baldo and M. Miozzo, "Spectrum-aware Channel and PHY layer modeling for ns3",
|
||||
Proceedings of ICST NSTools 2009, Pisa, Italy
|
||||
|
||||
|
||||
@@ -205,11 +205,11 @@ Usage
|
||||
|
||||
The main use case of the spectrum model is for developers who want to
|
||||
develop a new model for the PHY layer of some wireless technology to
|
||||
be used within ns-3.
|
||||
be used within ns-3.
|
||||
Here are some notes on how the spectrum module is expected to be used.
|
||||
|
||||
* ``SpectrumPhy`` and ``SpectrumChannel`` are abstract base classes. Real
|
||||
code will use classes that inherit from these classes.
|
||||
code will use classes that inherit from these classes.
|
||||
|
||||
* If you are implementing a new model for some wireless
|
||||
technology of your interest, and want to use the spectrum module,
|
||||
@@ -221,7 +221,7 @@ Here are some notes on how the spectrum module is expected to be used.
|
||||
instances of ``SpectrumModel`` are typically statically allocated,
|
||||
in order to allow several ``SpectrumValue`` instances to reference
|
||||
the same ``SpectrumModel`` instance.
|
||||
|
||||
|
||||
- a child class of ``SpectrumPhy`` which will handle transmission and
|
||||
reception of signals (including, if appropriate, interference
|
||||
and error modeling).
|
||||
@@ -238,21 +238,21 @@ Here are some notes on how the spectrum module is expected to be used.
|
||||
are quite generic. Chances are you can use them as-is. Whether you
|
||||
prefer one or the other it is just a matter of whether you will
|
||||
have a single SpectrumModel or multiple ones in your
|
||||
simulations.
|
||||
simulations.
|
||||
|
||||
* Typically, there will be a single SpectrumChannel instance to which
|
||||
several SpectrumPhy instances are plugged. The rule of thumb is
|
||||
that all PHYs that are interfering with each other shall be plugged
|
||||
on the same channel. Multiple SpectrumChannel instances are
|
||||
expected to be used mainly when simulating completely orthogonal
|
||||
channels; for example, when simulating the uplink and downlink
|
||||
channels; for example, when simulating the uplink and downlink
|
||||
of a Frequency Division Duplex system, it is a good choice to use
|
||||
two SpectrumChannel instances in order to reduce computational
|
||||
complexity.
|
||||
complexity.
|
||||
|
||||
* Different types of SpectrumPhy (i.e., instances of different child
|
||||
classes) can be plugged on the same SpectrumChannel instance. This
|
||||
is one of the main features of the
|
||||
is one of the main features of the
|
||||
spectrum module, to support inter-technology interference. For
|
||||
example, if you implement a WifiSpectrumPhy and a
|
||||
BluetoohSpectrumPhy, and plug both on a SpectrumChannel, then you'll
|
||||
@@ -265,7 +265,7 @@ Here are some notes on how the spectrum module is expected to be used.
|
||||
interference. A PHY device model is expected to use the
|
||||
``DynamicCast<>`` operator to determine if a signal is of a certain
|
||||
type it can attempt to receive. If not, the signal is normally
|
||||
expected to be considered as interference.
|
||||
expected to be considered as interference.
|
||||
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ Helpers
|
||||
|
||||
|
||||
The helpers provided in ``src/spectrum/helpers`` are mainly intended
|
||||
for the example implementations described in :ref:`sec-example-model-implementations`.
|
||||
for the example implementations described in :ref:`sec-example-model-implementations`.
|
||||
If you are developing your custom model based on the
|
||||
spectrum framework, you will probably prefer to define your own
|
||||
helpers.
|
||||
@@ -293,7 +293,7 @@ Attributes
|
||||
interference calculations. Just be careful to choose a value that
|
||||
does not make the interference calculations inaccurate.
|
||||
|
||||
* The example implementations described in :ref:`sec-example-model-implementations` also have several attributes.
|
||||
* The example implementations described in :ref:`sec-example-model-implementations` also have several attributes.
|
||||
|
||||
|
||||
|
||||
@@ -309,7 +309,7 @@ Output
|
||||
calclulated. **Note**: only single-frequency path loss is accounted
|
||||
for, see the attribute description.
|
||||
|
||||
* The example implementations described in :ref:`sec-example-model-implementations` also provide some trace sources.
|
||||
* The example implementations described in :ref:`sec-example-model-implementations` also provide some trace sources.
|
||||
|
||||
* The helper class ``SpectrumAnalyzerHelper`` can be conveniently
|
||||
used to generate an output text file containing the spectrogram
|
||||
@@ -317,14 +317,14 @@ Output
|
||||
be easily plotted with ``gnuplot``. For example, if your run the
|
||||
example ``adhoc-aloha-ideal-phy-with-microwave-oven`` you will get
|
||||
an output file called ``spectrum-analyzer-output-3-0.tr``. From
|
||||
this output file, you can generate a figure similar to
|
||||
this output file, you can generate a figure similar to
|
||||
:ref:`fig-spectrum-analyzer-example` by executing the following
|
||||
gnuplot commands:
|
||||
|
||||
.. sourcecode:: none
|
||||
|
||||
unset surface
|
||||
set pm3d at s
|
||||
set pm3d at s
|
||||
set palette
|
||||
set key off
|
||||
set view 50,50
|
||||
@@ -355,7 +355,7 @@ Troubleshooting
|
||||
scenarios, depending on the actual waveforms involved, the number
|
||||
of interferers, etc. Moreover, it is very important to use error
|
||||
models that are consistent with the interference model. The
|
||||
responsibility of ensuring that the models being used are correct
|
||||
responsibility of ensuring that the models being used are correct
|
||||
is left to the user.
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ numerical errors.
|
||||
|
||||
|
||||
Describe how the model has been tested/validated. What tests run in the
|
||||
test suite? How much API and code is covered by the tests? Again,
|
||||
test suite? How much API and code is covered by the tests? Again,
|
||||
references to outside published work may help here.
|
||||
|
||||
|
||||
@@ -411,7 +411,7 @@ cases are created corresponding to different PSDs of the intended
|
||||
signal and different amount of transmitted bytes. The test passes if
|
||||
the output of the error model (successful or failed) coincides with
|
||||
the expected one which was determine offline by manually calculating
|
||||
the achievable rate using Shannon's formula.
|
||||
the achievable rate using Shannon's formula.
|
||||
|
||||
|
||||
IdealPhy test
|
||||
@@ -434,7 +434,7 @@ following conditions are satisfied:
|
||||
:math:`1\%` of the PHY rate;
|
||||
|
||||
* if the PHY rate is not achievable, the application throughput shall
|
||||
be zero.
|
||||
be zero.
|
||||
|
||||
|
||||
|
||||
@@ -446,57 +446,57 @@ TV Transmitter Model
|
||||
====================
|
||||
|
||||
A TV Transmitter model is implemented by the ``TvSpectrumTransmitter`` class.
|
||||
This model enables transmission of realistic TV signals to be simulated and can
|
||||
be used for interference modeling. It provides a customizable power spectral
|
||||
density (PSD) model, with configurable attributes including the type of
|
||||
modulation (with models for analog, 8-VSB, and COFDM), signal bandwidth,
|
||||
power spectral density level, frequency, and transmission duration. A helper
|
||||
class, ``TvSpectrumTransmitterHelper``, is also provided to assist users in
|
||||
This model enables transmission of realistic TV signals to be simulated and can
|
||||
be used for interference modeling. It provides a customizable power spectral
|
||||
density (PSD) model, with configurable attributes including the type of
|
||||
modulation (with models for analog, 8-VSB, and COFDM), signal bandwidth,
|
||||
power spectral density level, frequency, and transmission duration. A helper
|
||||
class, ``TvSpectrumTransmitterHelper``, is also provided to assist users in
|
||||
setting up simulations.
|
||||
|
||||
Main Model Class
|
||||
################
|
||||
|
||||
The main TV Transmitter model class, ``TvSpectrumTransmitter``, provides a
|
||||
user-configurable PSD model that can be transmitted on the ``SpectrumChannel``.
|
||||
It inherits from ``SpectrumPhy`` and is comprised of attributes and methods to
|
||||
The main TV Transmitter model class, ``TvSpectrumTransmitter``, provides a
|
||||
user-configurable PSD model that can be transmitted on the ``SpectrumChannel``.
|
||||
It inherits from ``SpectrumPhy`` and is comprised of attributes and methods to
|
||||
create and transmit the signal on the channel.
|
||||
|
||||
.. _spectrum-tv-cofdm:
|
||||
|
||||
|
||||
.. figure:: figures/spectrum-tv-cofdm.*
|
||||
:align: center
|
||||
|
||||
8K COFDM signal spectrum generated from ``TvSpectrumTransmitter`` (Left) and
|
||||
8K COFDM signal spectrum generated from ``TvSpectrumTransmitter`` (Left) and
|
||||
theoretical COFDM signal spectrum [KoppCOFDM] (Right)
|
||||
|
||||
One of the user-configurable attributes is the type of modulation for the TV
|
||||
transmitter to use. The options are 8-VSB (Eight-Level Vestigial Sideband
|
||||
Modulation) which is notably used in the North America ATSC digital television
|
||||
standard, COFDM (Coded Orthogonal Frequency Division Multiplexing) which is
|
||||
notably used in the DVB-T and ISDB-T digital television standards adopted by
|
||||
various countries around the world, and analog modulation which is a legacy
|
||||
technology but is still being used by some countries today. To accomplish
|
||||
realistic PSD models for these modulation types, the signals’ PSDs were
|
||||
approximated from real standards and developed into models that are scalable by
|
||||
frequency and power. The COFDM PSD is approximated from Figure 12 (8k mode) of
|
||||
[KoppCOFDM], the 8-VSB PSD is approximated from Figure 3 of [Baron8VSB], and the
|
||||
analog PSD is approximated from Figure 4 of [QualcommAnalog]. Note that the
|
||||
analog model is approximated from the NTSC standard, but other analog modulation
|
||||
standards such as PAL have similar signals. The approximated COFDM PSD model is
|
||||
in 8K mode. The other configurable attributes are the start frequency,
|
||||
signal/channel bandwidth, base PSD, antenna type, starting time,
|
||||
One of the user-configurable attributes is the type of modulation for the TV
|
||||
transmitter to use. The options are 8-VSB (Eight-Level Vestigial Sideband
|
||||
Modulation) which is notably used in the North America ATSC digital television
|
||||
standard, COFDM (Coded Orthogonal Frequency Division Multiplexing) which is
|
||||
notably used in the DVB-T and ISDB-T digital television standards adopted by
|
||||
various countries around the world, and analog modulation which is a legacy
|
||||
technology but is still being used by some countries today. To accomplish
|
||||
realistic PSD models for these modulation types, the signals’ PSDs were
|
||||
approximated from real standards and developed into models that are scalable by
|
||||
frequency and power. The COFDM PSD is approximated from Figure 12 (8k mode) of
|
||||
[KoppCOFDM], the 8-VSB PSD is approximated from Figure 3 of [Baron8VSB], and the
|
||||
analog PSD is approximated from Figure 4 of [QualcommAnalog]. Note that the
|
||||
analog model is approximated from the NTSC standard, but other analog modulation
|
||||
standards such as PAL have similar signals. The approximated COFDM PSD model is
|
||||
in 8K mode. The other configurable attributes are the start frequency,
|
||||
signal/channel bandwidth, base PSD, antenna type, starting time,
|
||||
and transmit duration.
|
||||
|
||||
``TvSpectrumTransmitter`` uses ``IsotropicAntennaModel`` as its antenna model by
|
||||
default, but any model that inherits from ``AntennaModel`` is selectable, so
|
||||
directional antenna models can also be used. The propagation loss models used
|
||||
in simulation are configured in the ``SpectrumChannel`` that the user chooses to
|
||||
use. Terrain and spherical Earth/horizon effects may be supported in future ns-3
|
||||
``TvSpectrumTransmitter`` uses ``IsotropicAntennaModel`` as its antenna model by
|
||||
default, but any model that inherits from ``AntennaModel`` is selectable, so
|
||||
directional antenna models can also be used. The propagation loss models used
|
||||
in simulation are configured in the ``SpectrumChannel`` that the user chooses to
|
||||
use. Terrain and spherical Earth/horizon effects may be supported in future ns-3
|
||||
propagation loss models.
|
||||
|
||||
After the attributes are set, along with the ``SpectrumChannel``,
|
||||
``MobilityModel``, and node locations, the PSD of the TV transmitter signal can
|
||||
After the attributes are set, along with the ``SpectrumChannel``,
|
||||
``MobilityModel``, and node locations, the PSD of the TV transmitter signal can
|
||||
be created and transmitted on the channel.
|
||||
|
||||
.. _sec-tv-helper-class:
|
||||
@@ -504,103 +504,284 @@ be created and transmitted on the channel.
|
||||
Helper Class
|
||||
############
|
||||
|
||||
The helper class, ``TvSpectrumTransmitterHelper``, consists of features to
|
||||
assist users in setting up TV transmitters for their simulations. Functionality
|
||||
is also provided to easily simulate real-world scenarios.
|
||||
The helper class, ``TvSpectrumTransmitterHelper``, consists of features to
|
||||
assist users in setting up TV transmitters for their simulations. Functionality
|
||||
is also provided to easily simulate real-world scenarios.
|
||||
|
||||
.. _spectrum-tv-8vsb:
|
||||
|
||||
|
||||
.. figure:: figures/spectrum-tv-8vsb.*
|
||||
:align: center
|
||||
|
||||
North America ATSC channel 19 & 20 signals generated using
|
||||
``TvSpectrumTransmitterHelper`` (Left) and theoretical 8-VSB signal
|
||||
[Baron8VSB] (Right). Note that the theoretical signal is not shown in dB
|
||||
North America ATSC channel 19 & 20 signals generated using
|
||||
``TvSpectrumTransmitterHelper`` (Left) and theoretical 8-VSB signal
|
||||
[Baron8VSB] (Right). Note that the theoretical signal is not shown in dB
|
||||
while the ns-3 generated signals are.
|
||||
|
||||
Using this helper class, users can easily set up TV transmitters right after
|
||||
configuring attributes. Multiple transmitters can be created at a time. Also
|
||||
included are real characteristics of specific geographic regions that can be
|
||||
used to run realistic simulations. The regions currently included are
|
||||
North America, Europe, and Japan. The frequencies and bandwidth of each TV
|
||||
Using this helper class, users can easily set up TV transmitters right after
|
||||
configuring attributes. Multiple transmitters can be created at a time. Also
|
||||
included are real characteristics of specific geographic regions that can be
|
||||
used to run realistic simulations. The regions currently included are
|
||||
North America, Europe, and Japan. The frequencies and bandwidth of each TV
|
||||
channel for each these regions are provided.
|
||||
|
||||
.. _spectrum-tv-rand-geo-points:
|
||||
|
||||
|
||||
.. figure:: figures/spectrum-tv-rand-geo-points.*
|
||||
:align: center
|
||||
|
||||
Plot from MATLAB implementation of CreateRegionalTvTransmitters method in
|
||||
``TvSpectrumTransmitterHelper``. Shows 100 random points on Earth’s surface
|
||||
(with altitude 0) corresponding to TV transmitter locations within a 2000 km
|
||||
Plot from MATLAB implementation of CreateRegionalTvTransmitters method in
|
||||
``TvSpectrumTransmitterHelper``. Shows 100 random points on Earth’s surface
|
||||
(with altitude 0) corresponding to TV transmitter locations within a 2000 km
|
||||
radius of 35° latitude and -100° longitude.
|
||||
|
||||
A method (CreateRegionalTvTransmitters) is provided that enables users to
|
||||
randomly generate multiple TV transmitters from a specified region with a given
|
||||
density within a chosen radius around a point on Earth’s surface. The region,
|
||||
which determines the channel frequencies of the generated TV transmitters, can
|
||||
be specified to be one of the three provided, while the density determines the
|
||||
amount of transmitters generated. The TV transmitters' antenna heights
|
||||
(altitude) above Earth's surface can also be randomly generated to be within a
|
||||
given maximum altitude. This method models Earth as a perfect sphere, and
|
||||
generated location points are referenced accordingly in Earth-Centered
|
||||
Earth-Fixed Cartesian coordinates. Note that bodies of water on Earth are not
|
||||
considered in location point generation--TV transmitters can be generated
|
||||
A method (CreateRegionalTvTransmitters) is provided that enables users to
|
||||
randomly generate multiple TV transmitters from a specified region with a given
|
||||
density within a chosen radius around a point on Earth’s surface. The region,
|
||||
which determines the channel frequencies of the generated TV transmitters, can
|
||||
be specified to be one of the three provided, while the density determines the
|
||||
amount of transmitters generated. The TV transmitters' antenna heights
|
||||
(altitude) above Earth's surface can also be randomly generated to be within a
|
||||
given maximum altitude. This method models Earth as a perfect sphere, and
|
||||
generated location points are referenced accordingly in Earth-Centered
|
||||
Earth-Fixed Cartesian coordinates. Note that bodies of water on Earth are not
|
||||
considered in location point generation--TV transmitters can be generated
|
||||
anywhere on Earth around the origin point within the chosen maximum radius.
|
||||
|
||||
Examples
|
||||
########
|
||||
|
||||
Two example simulations are provided that demonstrate the functionality of the
|
||||
TV transmitter model. ``tv-trans-example`` simulates two 8-VSB TV transmitters
|
||||
with adjacent channel frequencies. ``tv-trans-regional-example`` simulates
|
||||
randomly generated COFDM TV transmitters (modeling the DVB-T standard)
|
||||
located around the Paris, France area with channel frequencies and bandwidths
|
||||
Two example simulations are provided that demonstrate the functionality of the
|
||||
TV transmitter model. ``tv-trans-example`` simulates two 8-VSB TV transmitters
|
||||
with adjacent channel frequencies. ``tv-trans-regional-example`` simulates
|
||||
randomly generated COFDM TV transmitters (modeling the DVB-T standard)
|
||||
located around the Paris, France area with channel frequencies and bandwidths
|
||||
corresponding to the European television channel allocations.
|
||||
|
||||
Testing
|
||||
#######
|
||||
|
||||
The ``tv-spectrum-transmitter`` test suite verifies the accuracy of the
|
||||
spectrum/PSD model in ``TvSpectrumTransmitter`` by testing if the maximum power
|
||||
spectral density, start frequency, and end frequency comply with expected values
|
||||
The ``tv-spectrum-transmitter`` test suite verifies the accuracy of the
|
||||
spectrum/PSD model in ``TvSpectrumTransmitter`` by testing if the maximum power
|
||||
spectral density, start frequency, and end frequency comply with expected values
|
||||
for various test cases.
|
||||
|
||||
The ``tv-helper-distribution`` test suite verifies the functionality of the
|
||||
method in ``TvSpectrumTransmitterHelper`` that generates a random number of TV
|
||||
transmitters based on the given density (low, medium, or high) and maximum
|
||||
number of TV channels. It verifies that the number of TV transmitters generated
|
||||
The ``tv-helper-distribution`` test suite verifies the functionality of the
|
||||
method in ``TvSpectrumTransmitterHelper`` that generates a random number of TV
|
||||
transmitters based on the given density (low, medium, or high) and maximum
|
||||
number of TV channels. It verifies that the number of TV transmitters generated
|
||||
does not exceed the expected bounds.
|
||||
|
||||
The CreateRegionalTvTransmitters method in ``TvSpectrumTransmitterHelper``
|
||||
described in :ref:`sec-tv-helper-class` uses two methods from the
|
||||
``GeographicPositions`` class in the Mobility module to generate the random
|
||||
Cartesian points on or above earth's surface around an origin point which
|
||||
correspond to TV transmitter positions. The first method converts Earth
|
||||
geographic coordinates to Earth-Centered Earth-Fixed (ECEF) Cartesian
|
||||
coordinates, and is tested in the ``geo-to-cartesian`` test suite by comparing
|
||||
(with 10 meter tolerance) its output with the output of the geographic to ECEF
|
||||
conversion function [MatlabGeo] of the MATLAB Mapping Toolbox for numerous
|
||||
test cases. The other used method generates random ECEF Cartesian points around
|
||||
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
|
||||
The CreateRegionalTvTransmitters method in ``TvSpectrumTransmitterHelper``
|
||||
described in :ref:`sec-tv-helper-class` uses two methods from the
|
||||
``GeographicPositions`` class in the Mobility module to generate the random
|
||||
Cartesian points on or above earth's surface around an origin point which
|
||||
correspond to TV transmitter positions. The first method converts Earth
|
||||
geographic coordinates to Earth-Centered Earth-Fixed (ECEF) Cartesian
|
||||
coordinates, and is tested in the ``geo-to-cartesian`` test suite by comparing
|
||||
(with 10 meter tolerance) its output with the output of the geographic to ECEF
|
||||
conversion function [MatlabGeo] of the MATLAB Mapping Toolbox for numerous
|
||||
test cases. The other used method generates random ECEF Cartesian points around
|
||||
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.
|
||||
|
||||
3GPP TR 38.901 fast fading model
|
||||
================================
|
||||
The framework described by TR 38.901 [TR38901]_ is a 3D statistical Spatial
|
||||
Channel Model supporting different propagation environments (e.g., urban,
|
||||
rural, indoor), multi-antenna operations and the modeling of wireless channels
|
||||
between 0.5 and 100 GHz.
|
||||
The overall channel is represented by the matrix H(t,τ), in which each
|
||||
entry H :sub:`u,s` (t,τ) corresponds to the impulse response of the channel between the
|
||||
s-th element of the transmitting antenna and the u-th element of the receiving
|
||||
antenna. H :sub:`u,s` (t,τ) is generated by the superposition of N different multi-path
|
||||
components, called clusters, each of which composed of M different rays.
|
||||
The channel matrix generation procedure accounts for large and small scale
|
||||
propagation phenomena. The classes ThreeGppSpectrumPropagationLossModel and
|
||||
ThreeGppChannelModel included in the spectrum module takes care of the generation
|
||||
of the channel coefficients and the computation of the frequency-dependent
|
||||
propagation loss.
|
||||
|
||||
Implementation
|
||||
##############
|
||||
|
||||
Our implementation is described in [Zugno]_. It is based on the model described
|
||||
in [Zhang]_, but the code has been refactored, extended, and aligned to TR 38.901
|
||||
[TR38901]_.
|
||||
The fundamental assumption behind this model is the channel reciprocity, i.e.,
|
||||
the impulse response of the channel between node a and node b is the same as
|
||||
between node b and node a.
|
||||
To deal with the equivalence of the channel between a and b, no matter who is
|
||||
the transmitter and who is the receiver, the model considers the pair of nodes
|
||||
to be composed by one "s" and one "u" node. The channel matrix, as well as other
|
||||
parameters, are saved and used under the assumption that, within a pair, the
|
||||
definition of the "s" and "u" node will always be the same. For more details,
|
||||
please have a look at the documentation of the classes
|
||||
ThreeGppChannelModel and ThreeGppSpectrumPropagationLossModel.
|
||||
|
||||
**Note:**
|
||||
|
||||
* Currently, no error model is provided; a link-to-system campaign may be
|
||||
needed to incorporate it in existing modules.
|
||||
|
||||
* The model does not include any spatial consistency update procedure
|
||||
(see [TR38901]_, Sec. 7.6.1). The implementation of this feature is left
|
||||
as future work.
|
||||
|
||||
* Issue regarding the blockage model: according to 3GPP TR 38.901 v15.0.0
|
||||
(2018-06) section 7.6.4.1, the blocking region for self-blocking is provided
|
||||
in LCS.
|
||||
However, here, clusterAOA and clusterZOA are in GCS and blocking check is
|
||||
performed for self-blocking similar to non-self blocking, that is in GCS.
|
||||
One would expect the angles to be transposed to LCS before checking self-blockage.
|
||||
|
||||
ThreeGppSpectrumPropagationLossModel
|
||||
####################################
|
||||
|
||||
The class ThreeGppSpectrumPropagationLossModel extends the SpectrumPropagationLossModel
|
||||
interface and enables the modeling of frequency
|
||||
dependent propagation phenomena. The main method is DoCalcRxPowerSpectralDensity,
|
||||
which takes as input the power spectral density (PSD) of the transmitted signal,
|
||||
the mobility models of the transmitting node and receiving node, and
|
||||
returns the PSD of the received signal.
|
||||
|
||||
Procedure used to compute the PSD of to compute the PSD of the received signal:
|
||||
|
||||
1. Retrieve the beamforming vectors
|
||||
To account for the beamforming, ThreeGppSpectrumPropagationLossModel has to
|
||||
retrieve the beamforming vectors of the transmitting and receiving antennas.
|
||||
The method DoCalcRxPowerSpectralDensity uses m_deviceAntennaMap to obtain the
|
||||
antenna objects associated to the transmitting and receiving devices, and calls
|
||||
the method GetCurrentBeamformingVector to retrieve the beamforming vectors.
|
||||
For each device using the channel, the m_deviceAntennaMap contains the associated
|
||||
antenna object of type ThreeGppAntennaArrayModel. Since the mapping is one-to-one,
|
||||
the model supports a single antenna object for each device.
|
||||
The m_deviceAntennaMap has to be initialized by inserting the device-antenna
|
||||
pairs using the method AddDevice.
|
||||
|
||||
2. Retrieve the channel matrix
|
||||
The ThreeGppSpectrumPropagationLossModel relies on the ThreeGppChannelModel class
|
||||
to obtain the channel matrix. In particular, it makes use of the method GetChannel,
|
||||
which returns a ThreeGppChannelMatrix object containing the channel
|
||||
matrix and other channel parameters.
|
||||
The ThreeGppChannelModel instance is automatically
|
||||
created in the the ThreeGppSpectrumPropagationLossModel constructor and it can
|
||||
be configured using the method SetChannelModelAttribute ().
|
||||
|
||||
4. Compute the long term component
|
||||
The method GetLongTerm returns the long term component obtained by multiplying
|
||||
the channel matrix and the beamforming vectors. To reduce the computational
|
||||
load, the long term components associated to the different channels are
|
||||
stored in the m_longTermMap and recomputed only if the associated channel
|
||||
matrix is updated or if the transmitting and/or receiving beamforming vectors
|
||||
have changed. Given the channel reciprocity assumption, for each node pair a
|
||||
single long term component is saved in the map.
|
||||
|
||||
5. Apply the small scale fading and compute the channel gain
|
||||
The method CalcBeamformingGain computes the channel gain in each sub-band and
|
||||
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.
|
||||
|
||||
ThreeGppChannelModel
|
||||
####################
|
||||
|
||||
The class ThreeGppChannelModel implements the channel matrix generation procedure
|
||||
described in Sec. of [TR38901]_.
|
||||
The main method is GetChannel, which takes as input the mobility models of
|
||||
the transmitter and receiver nodes, the associated antenna objects,
|
||||
and returns a ThreeGppChannelMatrix object containing:
|
||||
|
||||
* the channel matrix of size UxSxN, where U is the number of receiving antenna elements, S is the number of transmitting antenna elements and N is the number of clusters
|
||||
|
||||
* the clusters delays, as an array of size N
|
||||
|
||||
* the clusters arrival and departure angles, as a 2D array in which each row corresponds to a direction (AOA, ZOA, AOD, ZOD) and each column corresponds to a different cluster
|
||||
|
||||
* a time stamp indicating the time at which the channel matrix was generated
|
||||
|
||||
* the node IDs
|
||||
|
||||
* other channel parameters
|
||||
|
||||
The ThreeGppChannelMatrix objects are saved
|
||||
in the map m_channelMap and updated when the coherence time
|
||||
expires, or in case the LOS/NLOS channel condition changes.
|
||||
The coherence time can be configured through
|
||||
the attribute "UpdatePeriod", and should be chosen by taking into account all the
|
||||
factors that affects the channel variability, such as mobility, frequency,
|
||||
propagation scenario, etc. By default, it is set to 0, which means that the
|
||||
channel is recomputed only when the LOS/NLOS condition changes.
|
||||
It is possible to configure the propagation scenario and the operating frequency
|
||||
of interest through the attributes "Scenario" and "Frequency", respectively.
|
||||
|
||||
**Blockage model:** 3GPP TR 38.901 also provides an optional
|
||||
feature that can be used to model the blockage effect due to the
|
||||
presence of obstacles, such as trees, cars or humans, at the level
|
||||
of a single cluster. This differs from a complete blockage, which
|
||||
would result in an LOS to NLOS transition. Therefore, when this
|
||||
feature is enabled, an additional attenuation is added to certain
|
||||
clusters, depending on their angle of arrival. There are two possi-
|
||||
ble methods for the computation of the additional attenuation, i.e.,
|
||||
stochastic (Model A) and geometric (Model B). In this work, we
|
||||
used the implementation provided by [Zhang]_, which
|
||||
uses the stochastic method. In particular, the model is implemented by the
|
||||
method CalcAttenuationOfBlockage, which computes the additional attenuation.
|
||||
The blockage feature can be disable through the attribute "Blockage". Also, the
|
||||
attributes "NumNonselfBlocking", "PortraitMode" and "BlockerSpeed" can be used
|
||||
to configure the model.
|
||||
|
||||
Testing
|
||||
#######
|
||||
The test suite ThreeGppChannelTestSuite includes three test cases:
|
||||
|
||||
* ThreeGppChannelMatrixComputationTest checks if the channel matrix has the
|
||||
correct dimensions and if it correctly normalized
|
||||
|
||||
* ThreeGppChannelMatrixUpdateTest, which checks if the channel matrix is correctly
|
||||
updated when the coherence time exceeds
|
||||
|
||||
* ThreeGppSpectrumPropagationLossModelTest, which tests the functionalities of the
|
||||
class ThreeGppSpectrumPropagationLossModel. It builds a simple network composed of two
|
||||
nodes, computes the power spectral density received by the
|
||||
receiving node, and (i) checks if the long term components for the direct and the reverse link
|
||||
are the same, (ii) checks if the long term component is updated when changing the beamforming
|
||||
vectors, (iii) checks if the long term is updated when changing the channel matrix
|
||||
|
||||
**Note:** TR 38.901 includes a calibration procedure that can be used to validate
|
||||
the model, but it requires some additional features which are not currently
|
||||
implemented, thus is left as future work.
|
||||
|
||||
References
|
||||
##########
|
||||
|
||||
.. [Baron8VSB] Baron, Stanley. "First-Hand:Digital Television: The Digital
|
||||
Terrestrial Television Broadcasting (DTTB) Standard." IEEE Global History
|
||||
.. [Baron8VSB] Baron, Stanley. "First-Hand:Digital Television: The Digital
|
||||
Terrestrial Television Broadcasting (DTTB) Standard." IEEE Global History
|
||||
Network. <http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_Digital_Terrestrial_Television_Broadcasting_(DTTB)_Standard>.
|
||||
|
||||
.. [KoppCOFDM] Kopp, Carlo. "High Definition Television." High Definition
|
||||
.. [KoppCOFDM] Kopp, Carlo. "High Definition Television." High Definition
|
||||
Television. Air Power Australia. <http://www.ausairpower.net/AC-1100.html>.
|
||||
|
||||
.. [MatlabGeo] "Geodetic2ecef." Convert Geodetic to Geocentric (ECEF)
|
||||
Coordinates. The MathWorks, Inc.
|
||||
.. [MatlabGeo] "Geodetic2ecef." Convert Geodetic to Geocentric (ECEF)
|
||||
Coordinates. The MathWorks, Inc.
|
||||
<http://www.mathworks.com/help/map/ref/geodetic2ecef.html>.
|
||||
|
||||
.. [QualcommAnalog] Stephen Shellhammer, Ahmed Sadek, and Wenyi Zhang.
|
||||
"Technical Challenges for Cognitive Radio in the TV White Space Spectrum."
|
||||
.. [QualcommAnalog] Stephen Shellhammer, Ahmed Sadek, and Wenyi Zhang.
|
||||
"Technical Challenges for Cognitive Radio in the TV White Space Spectrum."
|
||||
Qualcomm Incorporated.
|
||||
|
||||
.. [TR38901] 3GPP. 2018. TR 38.901. Study on channel for frequencies from 0.5 to
|
||||
100 GHz. V.15.0.0. (2018-06).
|
||||
|
||||
.. [Zhang] Menglei Zhang, Michele Polese, Marco Mezzavilla, Sundeep Rangan,
|
||||
Michele Zorzi. "ns-3 Implementation of the 3GPP MIMO Channel Model for
|
||||
Frequency Spectrum above 6 GHz". In Proceedings of the Workshop on ns-3
|
||||
(WNS3 '17). 2017.
|
||||
|
||||
.. [Zugno] Tommaso Zugno, Michele Polese, Natale Patriciello, Biljana Bojovic,
|
||||
Sandra Lagen, Michele Zorzi. "Implementation of a Spatial Channel Model for
|
||||
ns-3". Submitted to the Workshop on ns-3 (WNS3 '20). 2020.
|
||||
Available: https://arxiv.org/abs/2002.09341
|
||||
|
||||
262
src/spectrum/examples/three-gpp-channel-example.cc
Normal file
262
src/spectrum/examples/three-gpp-channel-example.cc
Normal file
@@ -0,0 +1,262 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2019 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* This example shows how to configure the 3GPP channel model classes to
|
||||
* compute the SNR between two nodes.
|
||||
* The simulation involves two static nodes which are placed at a certain
|
||||
* distance from each other and communicates through a wireless channel at
|
||||
* 2 GHz with a bandwidth of 18 MHz. The default propagation environment is
|
||||
* 3D-urban macro (UMa) and it can be configured changing the value of the
|
||||
* string "scenario".
|
||||
* Each node hosts a SimpleNetDevice and has an antenna array with 4 elements.
|
||||
*/
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/three-gpp-channel-model.h"
|
||||
#include "ns3/three-gpp-antenna-array-model.h"
|
||||
#include <fstream>
|
||||
#include "ns3/three-gpp-spectrum-propagation-loss-model.h"
|
||||
#include "ns3/net-device.h"
|
||||
#include "ns3/simple-net-device.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/node-container.h"
|
||||
#include "ns3/mobility-model.h"
|
||||
#include "ns3/constant-position-mobility-model.h"
|
||||
#include "ns3/lte-spectrum-value-helper.h"
|
||||
#include "ns3/channel-condition-model.h"
|
||||
#include "ns3/three-gpp-propagation-loss-model.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ThreeGppChannelExample");
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
static Ptr<ThreeGppPropagationLossModel> m_propagationLossModel; //!< the PropagationLossModel object
|
||||
static Ptr<ThreeGppSpectrumPropagationLossModel> m_spectrumLossModel; //!< the SpectrumPropagationLossModel 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 posX = bPos.x - aPos.x;
|
||||
double phiAngle = atan ((bPos.y - aPos.y) / posX);
|
||||
|
||||
if (posX < 0)
|
||||
{
|
||||
phiAngle = phiAngle + M_PI;
|
||||
}
|
||||
if (phiAngle < 0)
|
||||
{
|
||||
phiAngle = phiAngle + 2 * M_PI;
|
||||
}
|
||||
|
||||
double hAngleRadian = fmod ((phiAngle + M_PI),2 * M_PI - M_PI); // the azimuth angle
|
||||
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 txPow the transmitting power in dBm
|
||||
* \param noiseFigure the noise figure in dB
|
||||
*/
|
||||
static void
|
||||
ComputeSnr (Ptr<MobilityModel> txMob, Ptr<MobilityModel> rxMob, double txPow, double noiseFigure)
|
||||
{
|
||||
// Create the tx PSD using the LteSpectrumValueHelper
|
||||
// 100 RBs corresponds to 18 MHz (1 RB = 180 kHz)
|
||||
// EARFCN 100 corresponds to 2125.00 MHz
|
||||
std::vector<int> activeRbs0 (100);
|
||||
for (int i = 0; i < 100 ; i++)
|
||||
{
|
||||
activeRbs0[i] = i;
|
||||
}
|
||||
Ptr<SpectrumValue> txPsd = LteSpectrumValueHelper::CreateTxPowerSpectralDensity (2100, 100, txPow, activeRbs0);
|
||||
Ptr<SpectrumValue> rxPsd = txPsd->Copy ();
|
||||
NS_LOG_DEBUG ("Average tx power " << 10*log10(Sum (*txPsd) * 180e3) << " dB");
|
||||
|
||||
// create the noise PSD
|
||||
Ptr<SpectrumValue> noisePsd = LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (2100, 100, noiseFigure);
|
||||
NS_LOG_DEBUG ("Average noise power " << 10*log10 (Sum (*noisePsd) * 180e3) << " dB");
|
||||
|
||||
// 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");
|
||||
|
||||
// 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 ("snr-trace.txt", std::ios::out | std::ios::app);
|
||||
f << Simulator::Now ().GetSeconds () << " " << 10 * log10 (Sum (*rxPsd) / Sum (*noisePsd)) << " " << propagationGainDb << std::endl;
|
||||
f.close ();
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
double frequency = 2125.0e6; // operating frequency in Hz (corresponds to EARFCN 2100)
|
||||
double txPow = 49.0; // tx power in dBm
|
||||
double noiseFigure = 9.0; // noise figure in dB
|
||||
double distance = 10.0; // distance between tx and rx nodes in meters
|
||||
uint32_t simTime = 10000; // simulation time in milliseconds
|
||||
uint32_t timeRes = 10; // time resolution in milliseconds
|
||||
std::string scenario = "UMa"; // 3GPP propagation scenario
|
||||
|
||||
Config::SetDefault ("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue(MilliSeconds (1))); // update the channel at each iteration
|
||||
Config::SetDefault ("ns3::ThreeGppChannelConditionModel::UpdatePeriod", TimeValue(MilliSeconds (0.0))); // do not update the channel condition
|
||||
|
||||
RngSeedManager::SetSeed(1);
|
||||
RngSeedManager::SetRun(1);
|
||||
|
||||
// create and configure the factories for the channel condition and propagation loss models
|
||||
ObjectFactory propagationLossModelFactory;
|
||||
ObjectFactory channelConditionModelFactory;
|
||||
if (scenario == "RMa")
|
||||
{
|
||||
propagationLossModelFactory.SetTypeId (ThreeGppRmaPropagationLossModel::GetTypeId ());
|
||||
channelConditionModelFactory.SetTypeId (ThreeGppRmaChannelConditionModel::GetTypeId ());
|
||||
}
|
||||
else if (scenario == "UMa")
|
||||
{
|
||||
propagationLossModelFactory.SetTypeId (ThreeGppUmaPropagationLossModel::GetTypeId ());
|
||||
channelConditionModelFactory.SetTypeId (ThreeGppUmaChannelConditionModel::GetTypeId ());
|
||||
}
|
||||
else if (scenario == "UMi-StreetCanyon")
|
||||
{
|
||||
propagationLossModelFactory.SetTypeId (ThreeGppUmiStreetCanyonPropagationLossModel::GetTypeId ());
|
||||
channelConditionModelFactory.SetTypeId (ThreeGppUmiStreetCanyonChannelConditionModel::GetTypeId ());
|
||||
}
|
||||
else if (scenario == "InH-OfficeOpen")
|
||||
{
|
||||
propagationLossModelFactory.SetTypeId (ThreeGppIndoorOfficePropagationLossModel::GetTypeId ());
|
||||
channelConditionModelFactory.SetTypeId (ThreeGppIndoorOpenOfficeChannelConditionModel::GetTypeId ());
|
||||
}
|
||||
else if (scenario == "InH-OfficeMixed")
|
||||
{
|
||||
propagationLossModelFactory.SetTypeId (ThreeGppIndoorOfficePropagationLossModel::GetTypeId ());
|
||||
channelConditionModelFactory.SetTypeId (ThreeGppIndoorMixedOfficeChannelConditionModel::GetTypeId ());
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("Unknown scenario");
|
||||
}
|
||||
|
||||
// create the propagation loss model
|
||||
m_propagationLossModel = propagationLossModelFactory.Create<ThreeGppPropagationLossModel> ();
|
||||
m_propagationLossModel->SetAttribute ("Frequency", DoubleValue (frequency));
|
||||
m_propagationLossModel->SetAttribute ("ShadowingEnabled", BooleanValue (false));
|
||||
|
||||
// create the spectrum propagation loss model
|
||||
m_spectrumLossModel = CreateObject<ThreeGppSpectrumPropagationLossModel> ();
|
||||
m_spectrumLossModel->SetChannelModelAttribute ("Frequency", DoubleValue (frequency));
|
||||
m_spectrumLossModel->SetChannelModelAttribute ("Scenario", StringValue (scenario));
|
||||
|
||||
// create the channel condition model and associate it with the spectrum and
|
||||
// propagation loss model
|
||||
Ptr<ChannelConditionModel> condModel = channelConditionModelFactory.Create<ThreeGppChannelConditionModel> ();
|
||||
m_spectrumLossModel->SetChannelModelAttribute ("ChannelConditionModel", PointerValue (condModel));
|
||||
m_propagationLossModel->SetChannelConditionModel (condModel);
|
||||
|
||||
// create the tx and rx 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 tx and rx mobility models, set the positions
|
||||
Ptr<MobilityModel> txMob = CreateObject<ConstantPositionMobilityModel> ();
|
||||
txMob->SetPosition (Vector (0.0,0.0,10.0));
|
||||
Ptr<MobilityModel> rxMob = CreateObject<ConstantPositionMobilityModel> ();
|
||||
rxMob->SetPosition (Vector (distance,0.0,1.6));
|
||||
|
||||
// assign the mobility models to the nodes
|
||||
nodes.Get (0)->AggregateObject (txMob);
|
||||
nodes.Get (1)->AggregateObject (rxMob);
|
||||
|
||||
// create the antenna objects and set their dimensions
|
||||
Ptr<ThreeGppAntennaArrayModel> txAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (2), "NumRows", UintegerValue (2));
|
||||
Ptr<ThreeGppAntennaArrayModel> rxAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (2), "NumRows", UintegerValue (2));
|
||||
|
||||
// initialize the devices in the ThreeGppSpectrumPropagationLossModel
|
||||
m_spectrumLossModel->AddDevice (txDev, txAntenna);
|
||||
m_spectrumLossModel->AddDevice (rxDev, rxAntenna);
|
||||
|
||||
// set the beamforming vectors
|
||||
DoBeamforming (txDev, txAntenna, rxDev);
|
||||
DoBeamforming (rxDev, rxAntenna, txDev);
|
||||
|
||||
for (int i = 0; i < floor (simTime / timeRes); i++)
|
||||
{
|
||||
Simulator::Schedule (MilliSeconds (timeRes*i), &ComputeSnr, txMob, rxMob, txPow, noiseFigure);
|
||||
}
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
}
|
||||
@@ -20,3 +20,7 @@ def build(bld):
|
||||
obj = bld.create_ns3_program('tv-trans-regional-example',
|
||||
['spectrum', 'mobility', 'core'])
|
||||
obj.source = 'tv-trans-regional-example.cc'
|
||||
|
||||
obj = bld.create_ns3_program('three-gpp-channel-example',
|
||||
['spectrum', 'mobility', 'core', 'lte'])
|
||||
obj.source = 'three-gpp-channel-example.cc'
|
||||
|
||||
1811
src/spectrum/model/three-gpp-channel-model.cc
Normal file
1811
src/spectrum/model/three-gpp-channel-model.cc
Normal file
File diff suppressed because it is too large
Load Diff
309
src/spectrum/model/three-gpp-channel-model.h
Normal file
309
src/spectrum/model/three-gpp-channel-model.h
Normal file
@@ -0,0 +1,309 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2015, NYU WIRELESS, Tandon School of Engineering,
|
||||
* New York University
|
||||
* Copyright (c) 2019 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_CHANNEL_H
|
||||
#define THREE_GPP_CHANNEL_H
|
||||
|
||||
#include <complex.h>
|
||||
#include "ns3/angles.h"
|
||||
#include <ns3/object.h>
|
||||
#include <ns3/nstime.h>
|
||||
#include <ns3/random-variable-stream.h>
|
||||
#include <ns3/boolean.h>
|
||||
#include <ns3/three-gpp-antenna-array-model.h>
|
||||
#include <unordered_map>
|
||||
#include <ns3/channel-condition-model.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class MobilityModel;
|
||||
|
||||
/**
|
||||
* \ingroup spectrum
|
||||
* \brief Channel Matrix Generation following 3GPP TR 38.901
|
||||
*
|
||||
* The class implements the channel matrix generation procedure
|
||||
* described in 3GPP TR 38.901.
|
||||
*
|
||||
* \see GetChannel
|
||||
*/
|
||||
class ThreeGppChannelModel : public Object
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppChannelModel ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~ThreeGppChannelModel ();
|
||||
|
||||
/**
|
||||
* Get the type ID
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId ();
|
||||
|
||||
typedef std::vector<double> DoubleVector; //!< type definition for vectors of doubles
|
||||
typedef std::vector<DoubleVector> Double2DVector; //!< type definition for matrices of doubles
|
||||
typedef std::vector<Double2DVector> Double3DVector; //!< type definition for 3D matrices of doubles
|
||||
typedef std::vector<ThreeGppAntennaArrayModel::ComplexVector> Complex2DVector; //!< type definition for complex matrices
|
||||
typedef std::vector<Complex2DVector> Complex3DVector; //!< type definition for complex 3D matrices
|
||||
|
||||
/**
|
||||
* Data structure that stores a channel realization
|
||||
*/
|
||||
struct ThreeGppChannelMatrix : public SimpleRefCount<ThreeGppChannelMatrix>
|
||||
{
|
||||
Complex3DVector m_channel; //!< channel matrix H[u][s][n].
|
||||
DoubleVector m_delay; //!< cluster delay.
|
||||
Double2DVector m_angle; //!< cluster angle angle[direction][n], where direction = 0(aoa), 1(zoa), 2(aod), 3(zod) in degree.
|
||||
Double2DVector m_nonSelfBlocking; //!< store the blockages
|
||||
Time m_generatedTime; //!< generation time
|
||||
std::pair<uint32_t, uint32_t> m_nodeIds; //!< the first element is the s-node ID, the second element is the u-node ID
|
||||
bool m_los; //!< true if LOS, false if NLOS
|
||||
|
||||
// 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*/
|
||||
Vector m_preLocUT; //!< location of UT when generating the previous channel
|
||||
Vector m_locUT; //!< location of UT
|
||||
Double2DVector m_norRvAngles; //!< stores the normal variable for random angles angle[cluster][id] generated for equation (7.6-11)-(7.6-14), where id = 0(aoa),1(zoa),2(aod),3(zod)
|
||||
double m_DS; //!< delay spread
|
||||
double m_K; //!< K factor
|
||||
uint8_t m_numCluster; //!< reduced cluster number;
|
||||
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
|
||||
|
||||
/**
|
||||
* Returns true if the ThreeGppChannelMatrix object was generated
|
||||
* considering node b as transmitter and node a as receiver.
|
||||
* \param aid id of the a node
|
||||
* \param bid id of the b node
|
||||
* \return true if b is the rx and a is the tx, false otherwise
|
||||
*/
|
||||
bool IsReverse (const uint32_t aId, const uint32_t bId) const
|
||||
{
|
||||
uint32_t sId, uId;
|
||||
std::tie (sId, uId) = m_nodeIds;
|
||||
NS_ASSERT_MSG ((sId == aId && uId == bId) || (sId == bId && uId == aId),
|
||||
"This matrix represents the channel between " << sId << " and " << uId);
|
||||
return (sId == bId && uId == aId);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the channel condition model
|
||||
* \param a pointer to the ChannelConditionModel object
|
||||
*/
|
||||
void SetChannelConditionModel (Ptr<ChannelConditionModel> model);
|
||||
|
||||
/**
|
||||
* Get the associated channel condition model
|
||||
* \return a pointer to the ChannelConditionModel object
|
||||
*/
|
||||
Ptr<ChannelConditionModel> GetChannelConditionModel () const;
|
||||
|
||||
/**
|
||||
* Sets the center frequency of the model
|
||||
* \param f the center frequency in Hz
|
||||
*/
|
||||
void SetFrequency (double f);
|
||||
|
||||
/**
|
||||
* Returns the center frequency
|
||||
* \return the center frequency in Hz
|
||||
*/
|
||||
double GetFrequency (void) const;
|
||||
|
||||
/**
|
||||
* Sets the propagation scenario
|
||||
* \param scenario the propagation scenario
|
||||
*/
|
||||
void SetScenario (const std::string &scenario);
|
||||
|
||||
/**
|
||||
* Returns the propagation scenario
|
||||
* \return the propagation scenario
|
||||
*/
|
||||
std::string GetScenario (void) const;
|
||||
|
||||
/**
|
||||
* Looks for the channel matrix associated to the aMob and bMob pair in m_channelMap.
|
||||
* If found, it checks if it has to be updated. If not found or if it has to
|
||||
* be updated, it generates a new uncorrelated channel matrix using the
|
||||
* method GetNewChannel and updates m_channelMap.
|
||||
*
|
||||
* We assume channel reciprocity between each node pair (i.e., H_ab = H_ba^T),
|
||||
* therefore GetChannel (a, b) and GetChannel (b, a) will return the same
|
||||
* ThreeGppChannelMatrix object.
|
||||
* To understand if the channel matrix corresponds to H_ab or H_ba, we provide
|
||||
* the method ThreeGppChannelMatrix::IsReverse. For instance, if the channel
|
||||
* matrix corresponds to H_ab, a call to IsReverse (idA, idB) will return
|
||||
* false, conversely, IsReverse (idB, idA) will return true.
|
||||
*
|
||||
* \param aMob mobility model of the a device
|
||||
* \param bMob mobility model of the b device
|
||||
* \param aAntenna antenna of the a device
|
||||
* \param bAntenna antenna of the b device
|
||||
* \return the channel matrix
|
||||
*/
|
||||
Ptr<const ThreeGppChannelMatrix> GetChannel (Ptr<const MobilityModel> aMob,
|
||||
Ptr<const MobilityModel> bMob,
|
||||
Ptr<const ThreeGppAntennaArrayModel> aAntenna,
|
||||
Ptr<const ThreeGppAntennaArrayModel> bAntenna);
|
||||
/**
|
||||
* \brief Assign a fixed random variable stream number to the random variables
|
||||
* used by this model.
|
||||
*
|
||||
* \param stream first stream index to use
|
||||
* \return the number of stream indices assigned by this model
|
||||
*/
|
||||
int64_t AssignStreams (int64_t stream);
|
||||
|
||||
static const uint8_t AOA_INDEX = 0; //!< index of the AOA value in the m_angle array
|
||||
static const uint8_t ZOA_INDEX = 1; //!< index of the ZOA value in the m_angle array
|
||||
static const uint8_t AOD_INDEX = 2; //!< index of the AOD value in the m_angle array
|
||||
static const uint8_t ZOD_INDEX = 3; //!< index of the ZOD value in the m_angle array
|
||||
|
||||
static const uint8_t PHI_INDEX = 0; //!< index of the PHI value in the m_nonSelfBlocking array
|
||||
static const uint8_t X_INDEX = 1; //!< index of the X value in the m_nonSelfBlocking array
|
||||
static const uint8_t THETA_INDEX = 2; //!< index of the THETA value in the m_nonSelfBlocking array
|
||||
static const uint8_t Y_INDEX = 3; //!< index of the Y value in the m_nonSelfBlocking array
|
||||
static const uint8_t R_INDEX = 4; //!< index of the R value in the m_nonSelfBlocking array
|
||||
|
||||
/**
|
||||
* Calculate the channel key using the Cantor function
|
||||
* \param x1 first value
|
||||
* \param x2 second value
|
||||
* \return \f$ (((x1 + x2) * (x1 + x2 + 1))/2) + x2; \f$
|
||||
*/
|
||||
static constexpr uint32_t GetKey (uint32_t x1, uint32_t x2)
|
||||
{
|
||||
return (((x1 + x2) * (x1 + x2 + 1)) / 2) + x2;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Data structure that stores the parameters of 3GPP TR 38.901, Table 7.5-6,
|
||||
* for a certain scenario
|
||||
*/
|
||||
struct ParamsTable : public SimpleRefCount<ParamsTable>
|
||||
{
|
||||
uint8_t m_numOfCluster = 0;
|
||||
uint8_t m_raysPerCluster = 0;
|
||||
double m_uLgDS = 0;
|
||||
double m_sigLgDS = 0;
|
||||
double m_uLgASD = 0;
|
||||
double m_sigLgASD = 0;
|
||||
double m_uLgASA = 0;
|
||||
double m_sigLgASA = 0;
|
||||
double m_uLgZSA = 0;
|
||||
double m_sigLgZSA = 0;
|
||||
double m_uLgZSD = 0;
|
||||
double m_sigLgZSD = 0;
|
||||
double m_offsetZOD = 0;
|
||||
double m_cDS = 0;
|
||||
double m_cASD = 0;
|
||||
double m_cASA = 0;
|
||||
double m_cZSA = 0;
|
||||
double m_uK = 0;
|
||||
double m_sigK = 0;
|
||||
double m_rTau = 0;
|
||||
double m_uXpr = 0;
|
||||
double m_sigXpr = 0;
|
||||
double m_perClusterShadowingStd = 0;
|
||||
|
||||
double m_sqrtC[7][7];
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 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;
|
||||
|
||||
/**
|
||||
* 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 sAntenna the s node antenna array
|
||||
* \param uAntenna the u node antenna array
|
||||
* \param uAngle the u node angle
|
||||
* \param sAngle the s node angle
|
||||
* \param dis2D the 2D distance between tx and rx
|
||||
* \param hBS the height of the BS
|
||||
* \param hUT the height of the UT
|
||||
* \return the channel realization
|
||||
*/
|
||||
Ptr<ThreeGppChannelMatrix> GetNewChannel (Vector locUT, bool los, bool o2i,
|
||||
Ptr<const ThreeGppAntennaArrayModel> sAntenna,
|
||||
Ptr<const ThreeGppAntennaArrayModel> uAntenna,
|
||||
Angles &uAngle, Angles &sAngle,
|
||||
double dis2D, double hBS, double hUT) const;
|
||||
|
||||
/**
|
||||
* Applies the blockage model A described in 3GPP TR 38.901
|
||||
* \param params the channel matrix
|
||||
* \param clusterAOA vector containing the azimuth angle of arrival for each cluster
|
||||
* \param clusterZOA vector containing the zenith angle of arrival for each cluster
|
||||
* \return vector containing the power attenuation for each cluster
|
||||
*/
|
||||
DoubleVector CalcAttenuationOfBlockage (Ptr<ThreeGppChannelMatrix> params,
|
||||
const DoubleVector &clusterAOA,
|
||||
const DoubleVector &clusterZOA) const;
|
||||
|
||||
/**
|
||||
* Check if the channel matrix has to be updated
|
||||
* \param channelMatrix channel matrix
|
||||
* \param isLos the current los condition
|
||||
* \return true if the channel matrix has to be updated, false otherwise
|
||||
*/
|
||||
bool ChannelMatrixNeedsUpdate (Ptr<const ThreeGppChannelMatrix> channelMatrix, bool isLos) const;
|
||||
|
||||
std::unordered_map<uint32_t, Ptr<ThreeGppChannelMatrix> > m_channelMap; //!< map containing the channel realizations
|
||||
Time m_updatePeriod; //!< the channel update period
|
||||
double m_frequency; //!< the operating frequency
|
||||
std::string m_scenario; //!< the 3GPP scenario
|
||||
Ptr<ChannelConditionModel> m_channelConditionModel; //!< the channel condition model
|
||||
Ptr<UniformRandomVariable> m_uniformRv; //!< uniform random variable
|
||||
Ptr<NormalRandomVariable> m_normalRv; //!< normal random variable
|
||||
|
||||
// parameters for the blockage model
|
||||
bool m_blockage; //!< enables the blockage model A
|
||||
uint16_t m_numNonSelfBlocking; //!< number of non-self-blocking regions
|
||||
bool m_portraitMode; //!< true if potrait mode, false if landscape
|
||||
double m_blockerSpeed; //!< the blocker speed
|
||||
};
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* THREE_GPP_CHANNEL_H */
|
||||
293
src/spectrum/model/three-gpp-spectrum-propagation-loss-model.cc
Normal file
293
src/spectrum/model/three-gpp-spectrum-propagation-loss-model.cc
Normal file
@@ -0,0 +1,293 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2015, NYU WIRELESS, Tandon School of Engineering,
|
||||
* New York University
|
||||
* Copyright (c) 2019 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 "ns3/log.h"
|
||||
#include "three-gpp-spectrum-propagation-loss-model.h"
|
||||
#include "ns3/net-device.h"
|
||||
#include "ns3/three-gpp-antenna-array-model.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/channel-condition-model.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include <map>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ThreeGppSpectrumPropagationLossModel");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ThreeGppSpectrumPropagationLossModel);
|
||||
|
||||
ThreeGppSpectrumPropagationLossModel::ThreeGppSpectrumPropagationLossModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_channelModel = CreateObject<ThreeGppChannelModel> ();
|
||||
}
|
||||
|
||||
ThreeGppSpectrumPropagationLossModel::~ThreeGppSpectrumPropagationLossModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
TypeId
|
||||
ThreeGppSpectrumPropagationLossModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::ThreeGppSpectrumPropagationLossModel")
|
||||
.SetParent<SpectrumPropagationLossModel> ()
|
||||
.SetGroupName ("Spectrum")
|
||||
.AddConstructor<ThreeGppSpectrumPropagationLossModel> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppSpectrumPropagationLossModel::AddDevice (Ptr<NetDevice> n, Ptr<const ThreeGppAntennaArrayModel> a)
|
||||
{
|
||||
NS_ASSERT_MSG (m_deviceAntennaMap.find (n->GetNode ()->GetId ()) == m_deviceAntennaMap.end (), "Device is already present in the map");
|
||||
m_deviceAntennaMap.insert (std::make_pair (n->GetNode ()->GetId (), a));
|
||||
}
|
||||
|
||||
double
|
||||
ThreeGppSpectrumPropagationLossModel::GetFrequency () const
|
||||
{
|
||||
DoubleValue freq;
|
||||
m_channelModel->GetAttribute ("Frequency", freq);
|
||||
return freq.Get ();
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppSpectrumPropagationLossModel::SetChannelModelAttribute (const std::string &name, const AttributeValue &value)
|
||||
{
|
||||
m_channelModel->SetAttribute (name, value);
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppSpectrumPropagationLossModel::GetChannelModelAttribute (const std::string &name, AttributeValue &value) const
|
||||
{
|
||||
m_channelModel->GetAttribute (name, value);
|
||||
}
|
||||
|
||||
ThreeGppAntennaArrayModel::ComplexVector
|
||||
ThreeGppSpectrumPropagationLossModel::CalcLongTerm (Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> params,
|
||||
const ThreeGppAntennaArrayModel::ComplexVector &sW,
|
||||
const ThreeGppAntennaArrayModel::ComplexVector &uW) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
uint16_t sAntenna = static_cast<uint16_t> (sW.size ());
|
||||
uint16_t uAntenna = static_cast<uint16_t> (uW.size ());
|
||||
|
||||
NS_LOG_DEBUG ("CalcLongTerm with sAntenna " << sAntenna << " uAntenna " << uAntenna);
|
||||
//store the long term part to reduce computation load
|
||||
//only the small scale fading needs to be updated if the large scale parameters and antenna weights remain unchanged.
|
||||
ThreeGppAntennaArrayModel::ComplexVector longTerm;
|
||||
uint8_t numCluster = static_cast<uint8_t> (params->m_channel[0][0].size ());
|
||||
|
||||
for (uint8_t cIndex = 0; cIndex < numCluster; cIndex++)
|
||||
{
|
||||
std::complex<double> txSum (0,0);
|
||||
for (uint16_t sIndex = 0; sIndex < sAntenna; sIndex++)
|
||||
{
|
||||
std::complex<double> rxSum (0,0);
|
||||
for (uint16_t uIndex = 0; uIndex < uAntenna; uIndex++)
|
||||
{
|
||||
rxSum = rxSum + uW[uIndex] * params->m_channel[uIndex][sIndex][cIndex];
|
||||
}
|
||||
txSum = txSum + sW[sIndex] * rxSum;
|
||||
}
|
||||
longTerm.push_back (txSum);
|
||||
}
|
||||
return longTerm;
|
||||
}
|
||||
|
||||
Ptr<SpectrumValue>
|
||||
ThreeGppSpectrumPropagationLossModel::CalcBeamformingGain (Ptr<SpectrumValue> txPsd,
|
||||
ThreeGppAntennaArrayModel::ComplexVector longTerm,
|
||||
Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> params,
|
||||
const ns3::Vector &sSpeed, const ns3::Vector &uSpeed) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
Ptr<SpectrumValue> tempPsd = Copy<SpectrumValue> (txPsd);
|
||||
|
||||
//channel[rx][tx][cluster]
|
||||
uint8_t numCluster = static_cast<uint8_t> (params->m_channel[0][0].size ());
|
||||
|
||||
// compute the doppler term
|
||||
// NOTE the update of Doppler is simplified by only taking the center angle of
|
||||
// each cluster in to consideration.
|
||||
double slotTime = Simulator::Now ().GetSeconds ();
|
||||
ThreeGppAntennaArrayModel::ComplexVector doppler;
|
||||
for (uint8_t cIndex = 0; cIndex < numCluster; cIndex++)
|
||||
{
|
||||
//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[ThreeGppChannelModel::ZOA_INDEX][cIndex] * M_PI / 180) * cos (params->m_angle[ThreeGppChannelModel::AOA_INDEX][cIndex] * M_PI / 180) * uSpeed.x
|
||||
+ sin (params->m_angle[ThreeGppChannelModel::ZOA_INDEX][cIndex] * M_PI / 180) * sin (params->m_angle[ThreeGppChannelModel::AOA_INDEX][cIndex] * M_PI / 180) * uSpeed.y
|
||||
+ cos (params->m_angle[ThreeGppChannelModel::ZOA_INDEX][cIndex] * M_PI / 180) * uSpeed.z)
|
||||
+ (sin (params->m_angle[ThreeGppChannelModel::ZOD_INDEX][cIndex] * M_PI / 180) * cos (params->m_angle[ThreeGppChannelModel::AOD_INDEX][cIndex] * M_PI / 180) * sSpeed.x
|
||||
+ sin (params->m_angle[ThreeGppChannelModel::ZOD_INDEX][cIndex] * M_PI / 180) * sin (params->m_angle[ThreeGppChannelModel::AOD_INDEX][cIndex] * M_PI / 180) * sSpeed.y
|
||||
+ cos (params->m_angle[ThreeGppChannelModel::ZOD_INDEX][cIndex] * M_PI / 180) * sSpeed.z))
|
||||
* slotTime * GetFrequency () / 3e8;
|
||||
doppler.push_back (exp (std::complex<double> (0, temp_doppler)));
|
||||
}
|
||||
|
||||
// apply the doppler term and the propagation delay to the long term component
|
||||
// to obtain the beamforming gain
|
||||
auto vit = tempPsd->ValuesBegin (); // psd iterator
|
||||
auto sbit = tempPsd->ConstBandsBegin(); // band iterator
|
||||
while (vit != tempPsd->ValuesEnd ())
|
||||
{
|
||||
std::complex<double> subsbandGain (0.0,0.0);
|
||||
if ((*vit) != 0.00)
|
||||
{
|
||||
double fsb = (*sbit).fc; // center frequency of the sub-band
|
||||
for (uint8_t cIndex = 0; cIndex < numCluster; cIndex++)
|
||||
{
|
||||
double delay = -2 * M_PI * fsb * (params->m_delay[cIndex]);
|
||||
subsbandGain = subsbandGain + longTerm[cIndex] * doppler[cIndex] * exp (std::complex<double> (0, delay));
|
||||
}
|
||||
*vit = (*vit) * (norm (subsbandGain));
|
||||
}
|
||||
vit++;
|
||||
sbit++;
|
||||
}
|
||||
return tempPsd;
|
||||
}
|
||||
|
||||
ThreeGppAntennaArrayModel::ComplexVector
|
||||
ThreeGppSpectrumPropagationLossModel::GetLongTerm (uint32_t aId, uint32_t bId,
|
||||
Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> channelMatrix,
|
||||
const ThreeGppAntennaArrayModel::ComplexVector &aW,
|
||||
const ThreeGppAntennaArrayModel::ComplexVector &bW) const
|
||||
{
|
||||
ThreeGppAntennaArrayModel::ComplexVector longTerm; // vector containing the long term component for each cluster
|
||||
|
||||
// check if the channel matrix was generated considering a as the s-node and
|
||||
// b as the u-node or viceversa
|
||||
ThreeGppAntennaArrayModel::ComplexVector sW, uW;
|
||||
if (!channelMatrix->IsReverse (aId, bId))
|
||||
{
|
||||
sW = aW;
|
||||
uW = bW;
|
||||
}
|
||||
else
|
||||
{
|
||||
sW = bW;
|
||||
uW = aW;
|
||||
}
|
||||
|
||||
// compute the long term key, the key is unique for each tx-rx pair
|
||||
uint32_t x1 = std::min (aId, bId);
|
||||
uint32_t x2 = std::max (aId, bId);
|
||||
uint32_t longTermId = ThreeGppChannelModel::GetKey (x1, x2);
|
||||
|
||||
bool update = false; // indicates whether the long term has to be updated
|
||||
bool notFound = false; // indicates if the long term has not been computed yet
|
||||
|
||||
// look for the long term in the map and check if it is valid
|
||||
if (m_longTermMap.find (longTermId) != m_longTermMap.end ())
|
||||
{
|
||||
NS_LOG_DEBUG ("found the long term component in the map");
|
||||
longTerm = m_longTermMap[longTermId]->m_longTerm;
|
||||
|
||||
// check if the channel matrix has been updated
|
||||
// or the s beam has been changed
|
||||
// or the u beam has been changed
|
||||
update = (m_longTermMap[longTermId]->m_channel->m_generatedTime != channelMatrix->m_generatedTime
|
||||
|| m_longTermMap[longTermId]->m_sW != sW
|
||||
|| m_longTermMap[longTermId]->m_uW != uW);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("long term component NOT found");
|
||||
notFound = true;
|
||||
}
|
||||
|
||||
if (update || notFound)
|
||||
{
|
||||
NS_LOG_DEBUG ("compute the long term");
|
||||
// compute the long term component
|
||||
longTerm = CalcLongTerm (channelMatrix, sW, uW);
|
||||
|
||||
// store the long term
|
||||
Ptr<LongTerm> longTermItem = Create<LongTerm> ();
|
||||
longTermItem->m_longTerm = longTerm;
|
||||
longTermItem->m_channel = channelMatrix;
|
||||
longTermItem->m_sW = sW;
|
||||
longTermItem->m_uW = uW;
|
||||
|
||||
m_longTermMap[longTermId] = longTermItem;
|
||||
}
|
||||
|
||||
return longTerm;
|
||||
}
|
||||
|
||||
Ptr<SpectrumValue>
|
||||
ThreeGppSpectrumPropagationLossModel::DoCalcRxPowerSpectralDensity (Ptr<const SpectrumValue> txPsd,
|
||||
Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
uint32_t aId = a->GetObject<Node> ()->GetId (); // id of the node a
|
||||
uint32_t bId = b->GetObject<Node> ()->GetId (); // id of the node b
|
||||
|
||||
NS_ASSERT (aId != bId);
|
||||
NS_ASSERT_MSG (a->GetDistanceFrom (b) > 0.0, "The position of a and b devices cannot be the same");
|
||||
|
||||
Ptr<SpectrumValue> rxPsd = Copy<SpectrumValue> (txPsd);
|
||||
|
||||
// retrieve the antenna of device a
|
||||
NS_ASSERT_MSG (m_deviceAntennaMap.find (aId) != m_deviceAntennaMap.end (), "Antenna not found for node " << aId);
|
||||
Ptr<const ThreeGppAntennaArrayModel> aAntenna = m_deviceAntennaMap.at (aId);
|
||||
NS_LOG_DEBUG ("a node " << a->GetObject<Node> () << " antenna " << aAntenna);
|
||||
|
||||
// retrieve the antenna of the device b
|
||||
NS_ASSERT_MSG (m_deviceAntennaMap.find (bId) != m_deviceAntennaMap.end (), "Antenna not found for device " << bId);
|
||||
Ptr<const ThreeGppAntennaArrayModel> bAntenna = m_deviceAntennaMap.at (bId);
|
||||
NS_LOG_DEBUG ("b node " << bId << " antenna " << bAntenna);
|
||||
|
||||
if (aAntenna->IsOmniTx () || bAntenna->IsOmniTx () )
|
||||
{
|
||||
NS_LOG_LOGIC ("Omni transmission, do nothing.");
|
||||
return rxPsd;
|
||||
}
|
||||
|
||||
Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> channelMatrix = m_channelModel->GetChannel (a, b, aAntenna, bAntenna);
|
||||
|
||||
// get the precoding and combining vectors
|
||||
ThreeGppAntennaArrayModel::ComplexVector aW = aAntenna->GetBeamformingVector ();
|
||||
ThreeGppAntennaArrayModel::ComplexVector bW = bAntenna->GetBeamformingVector ();
|
||||
|
||||
// retrieve the long term component
|
||||
ThreeGppAntennaArrayModel::ComplexVector longTerm = GetLongTerm (aId, bId, channelMatrix, aW, bW);
|
||||
|
||||
// apply the beamforming gain
|
||||
rxPsd = CalcBeamformingGain (rxPsd, longTerm, channelMatrix, a->GetVelocity (), b->GetVelocity ());
|
||||
|
||||
return rxPsd;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
181
src/spectrum/model/three-gpp-spectrum-propagation-loss-model.h
Normal file
181
src/spectrum/model/three-gpp-spectrum-propagation-loss-model.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2015, NYU WIRELESS, Tandon School of Engineering,
|
||||
* New York University
|
||||
* Copyright (c) 2019 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_SPECTRUM_PROPAGATION_LOSS_H
|
||||
#define THREE_GPP_SPECTRUM_PROPAGATION_LOSS_H
|
||||
|
||||
#include "ns3/spectrum-propagation-loss-model.h"
|
||||
#include <complex.h>
|
||||
#include <map>
|
||||
#include "ns3/three-gpp-channel-model.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class NetDevice;
|
||||
class ChannelConditionModel;
|
||||
class ChannelCondition;
|
||||
|
||||
/**
|
||||
* \ingroup spectrum
|
||||
* \brief 3GPP Spectrum Propagation Loss Model
|
||||
*
|
||||
* This class models the frequency dependent propagation phenomena in the way
|
||||
* described by 3GPP TR 38.901 document. The main method is DoCalcRxPowerSpectralDensity,
|
||||
* which takes as input the power spectral density (PSD) of the transmitted signal,
|
||||
* the mobility models of the transmitting node and receiving node, and
|
||||
* returns the PSD of the received signal.
|
||||
*
|
||||
* \see ThreeGppChannelModel
|
||||
* \see ThreeGppAntennaArrayModel
|
||||
* \see ChannelCondition
|
||||
*/
|
||||
class ThreeGppSpectrumPropagationLossModel : public SpectrumPropagationLossModel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppSpectrumPropagationLossModel ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~ThreeGppSpectrumPropagationLossModel ();
|
||||
|
||||
/**
|
||||
* Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId ();
|
||||
|
||||
/**
|
||||
* Add a device-antenna pair
|
||||
* \param n a pointer to the NetDevice
|
||||
* \param a a pointer to the associated ThreeGppAntennaArrayModel
|
||||
*/
|
||||
void AddDevice (Ptr<NetDevice> n, Ptr<const ThreeGppAntennaArrayModel> a);
|
||||
|
||||
|
||||
/**
|
||||
* Sets the value of an attribute belonging to the associated
|
||||
* ThreeGppChannelModel instance
|
||||
* \param name name of the attribute
|
||||
* \param value the attribute value
|
||||
*/
|
||||
void SetChannelModelAttribute (const std::string &name, const AttributeValue &value);
|
||||
|
||||
/**
|
||||
* Returns the value of an attribute belonging to the associated
|
||||
* ThreeGppChannelModel instance
|
||||
* \param name name of the attribute
|
||||
* \param where the result should be stored
|
||||
*/
|
||||
void GetChannelModelAttribute (const std::string &name, AttributeValue &value) const;
|
||||
|
||||
/**
|
||||
* \brief Computes the received PSD.
|
||||
*
|
||||
* This function computes the received PSD by applying the 3GPP fast fading
|
||||
* model and the beamforming gain.
|
||||
* In particular, it retrieves the matrix representing the channel between
|
||||
* node a and node b, computes the corresponding long term component, i.e.,
|
||||
* the product between the cluster matrices and the TX and RX beamforming
|
||||
* vectors (w_rx^T H^n_ab w_tx), and accounts for the Doppler component and
|
||||
* the propagation delay.
|
||||
* To reduce the computational load, the long term component associated with
|
||||
* a certain channel is cached and recomputed only when the channel realization
|
||||
* is updated, or when the beamforming vectors change.
|
||||
*
|
||||
* \param txPsd tx PSD
|
||||
* \param a first node mobility model
|
||||
* \param b second node mobility model
|
||||
*
|
||||
* \return the received PSD
|
||||
*/
|
||||
virtual Ptr<SpectrumValue> DoCalcRxPowerSpectralDensity (Ptr<const SpectrumValue> txPsd,
|
||||
Ptr<const MobilityModel> a,
|
||||
Ptr<const MobilityModel> b) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Data structure that stores the long term component for a tx-rx pair
|
||||
*/
|
||||
struct LongTerm : public SimpleRefCount<LongTerm>
|
||||
{
|
||||
ThreeGppAntennaArrayModel::ComplexVector m_longTerm; //!< vector containing the long term component for each cluster
|
||||
Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> m_channel; //!< pointer to the channel matrix used to compute the long term
|
||||
ThreeGppAntennaArrayModel::ComplexVector m_sW; //!< the beamforming vector for the node s used to compute the long term
|
||||
ThreeGppAntennaArrayModel::ComplexVector m_uW; //!< the beamforming vector for the node u used to compute the long term
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the operating frequency
|
||||
* \return the operating frequency in Hz
|
||||
*/
|
||||
double GetFrequency () const;
|
||||
|
||||
/**
|
||||
* Looks for the long term component in m_longTermMap. If found, checks
|
||||
* whether it has to be updated. If not found or if it has to be updated,
|
||||
* calls the method CalcLongTerm to compute it.
|
||||
* \param aId id of the first node
|
||||
* \param bId id of the second node
|
||||
* \param channelMatrix the channel matrix
|
||||
* \param aW the beamforming vector of the first device
|
||||
* \param bW the beamforming vector of the second device
|
||||
* \return vector containing the long term compoenent for each cluster
|
||||
*/
|
||||
ThreeGppAntennaArrayModel::ComplexVector GetLongTerm (uint32_t aId, uint32_t bId,
|
||||
Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> channelMatrix,
|
||||
const ThreeGppAntennaArrayModel::ComplexVector &aW,
|
||||
const ThreeGppAntennaArrayModel::ComplexVector &bW) const;
|
||||
/**
|
||||
* Computes the long term component
|
||||
* \param channelMatrix the channel matrix H
|
||||
* \param sW the beamforming vector of the s device
|
||||
* \param uW the beamforming vector of the u device
|
||||
* \return the long term component
|
||||
*/
|
||||
ThreeGppAntennaArrayModel::ComplexVector CalcLongTerm (Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> channelMatrix,
|
||||
const ThreeGppAntennaArrayModel::ComplexVector &sW,
|
||||
const ThreeGppAntennaArrayModel::ComplexVector &uW) const;
|
||||
|
||||
/**
|
||||
* Computes the beamforming gain and applies it to the tx PSD
|
||||
* \param txPsd the tx PSD
|
||||
* \param longTerm the long term component
|
||||
* \param params The channel matrix
|
||||
* \param sSpeed speed of the first node
|
||||
* \param uSpeed speed of the second node
|
||||
* \return the rx PSD
|
||||
*/
|
||||
Ptr<SpectrumValue> CalcBeamformingGain (Ptr<SpectrumValue> txPsd,
|
||||
ThreeGppAntennaArrayModel::ComplexVector longTerm,
|
||||
Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> params,
|
||||
const Vector &sSpeed, const Vector &uSpeed) const;
|
||||
|
||||
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<ThreeGppChannelModel> m_channelModel; //!< the model to generate the channel matrix
|
||||
};
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* THREE_GPP_SPECTRUM_PROPAGATION_LOSS_H */
|
||||
577
src/spectrum/test/three-gpp-channel-test-suite.cc
Normal file
577
src/spectrum/test/three-gpp-channel-test-suite.cc
Normal file
@@ -0,0 +1,577 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2019 SIGNET Lab, Department of Information Engineering,
|
||||
*
|
||||
* 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/log.h"
|
||||
#include "ns3/abort.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/angles.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/node-container.h"
|
||||
#include "ns3/constant-position-mobility-model.h"
|
||||
#include "ns3/three-gpp-antenna-array-model.h"
|
||||
#include "ns3/three-gpp-channel-model.h"
|
||||
#include "ns3/simple-net-device.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/channel-condition-model.h"
|
||||
#include "ns3/three-gpp-spectrum-propagation-loss-model.h"
|
||||
#include "ns3/wifi-spectrum-value-helper.h"
|
||||
#include "ns3/buildings-channel-condition-model.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ThreeGppChannelTestSuite");
|
||||
|
||||
/**
|
||||
* Test case for the ThreeGppChannelModel class.
|
||||
* 1) check if the channel matrix has the correct dimensions
|
||||
* 2) check if the channel matrix is correctly normalized
|
||||
*/
|
||||
class ThreeGppChannelMatrixComputationTest : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppChannelMatrixComputationTest ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreeGppChannelMatrixComputationTest ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Build the test scenario
|
||||
*/
|
||||
virtual void DoRun (void);
|
||||
|
||||
/**
|
||||
* Compute the Frobenius norm of the channel matrix and stores it in m_normVector
|
||||
* \param channelModel the ThreeGppChannelModel object used to generate the channel matrix
|
||||
* \param txMob the mobility model of the first node
|
||||
* \param rxMob the mobility model of the second node
|
||||
* \param txAntenna the antenna object associated to the first node
|
||||
* \param rxAntenna the antenna object associated to the second node
|
||||
*/
|
||||
void DoComputeNorm (Ptr<ThreeGppChannelModel> channelModel, Ptr<MobilityModel> txMob, Ptr<MobilityModel> rxMob, Ptr<ThreeGppAntennaArrayModel> txAntenna, Ptr<ThreeGppAntennaArrayModel> rxAntenna);
|
||||
|
||||
std::vector<double> m_normVector; //!< each element is the norm of a channel realization
|
||||
};
|
||||
|
||||
ThreeGppChannelMatrixComputationTest::ThreeGppChannelMatrixComputationTest ()
|
||||
: TestCase ("Check the dimensions and the norm of the channel matrix")
|
||||
{
|
||||
}
|
||||
|
||||
ThreeGppChannelMatrixComputationTest::~ThreeGppChannelMatrixComputationTest ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppChannelMatrixComputationTest::DoComputeNorm (Ptr<ThreeGppChannelModel> channelModel, Ptr<MobilityModel> txMob, Ptr<MobilityModel> rxMob, Ptr<ThreeGppAntennaArrayModel> txAntenna, Ptr<ThreeGppAntennaArrayModel> rxAntenna)
|
||||
{
|
||||
uint64_t txAntennaElements = txAntenna->GetNumberOfElements ();
|
||||
uint64_t rxAntennaElements = rxAntenna->GetNumberOfElements ();
|
||||
|
||||
Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> channelMatrix = channelModel->GetChannel (txMob, rxMob, txAntenna, rxAntenna);
|
||||
|
||||
double channelNorm = 0;
|
||||
uint8_t numTotClusters = channelMatrix->m_channel.at (0).at (0).size ();
|
||||
for (uint8_t cIndex = 0; cIndex < numTotClusters; cIndex++)
|
||||
{
|
||||
double clusterNorm = 0;
|
||||
for (uint64_t sIndex = 0; sIndex < txAntennaElements; sIndex++)
|
||||
{
|
||||
for (uint32_t uIndex = 0; uIndex < rxAntennaElements; uIndex++)
|
||||
{
|
||||
clusterNorm += std::pow (std::abs (channelMatrix->m_channel.at (uIndex).at (sIndex).at (cIndex)), 2);
|
||||
}
|
||||
}
|
||||
channelNorm += clusterNorm;
|
||||
}
|
||||
m_normVector.push_back (channelNorm);
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppChannelMatrixComputationTest::DoRun (void)
|
||||
{
|
||||
// Build the scenario for the test
|
||||
uint8_t txAntennaElements[] {2, 2}; // tx antenna dimensions
|
||||
uint8_t rxAntennaElements[] {2, 2}; // rx antenna dimensions
|
||||
uint32_t updatePeriodMs = 100; // update period in ms
|
||||
|
||||
// create the channel condition model
|
||||
Ptr<ChannelConditionModel> channelConditionModel = CreateObject<NeverLosChannelConditionModel> ();
|
||||
|
||||
// create the ThreeGppChannelModel object used to generate the channel matrix
|
||||
Ptr<ThreeGppChannelModel> channelModel = CreateObject<ThreeGppChannelModel> ();
|
||||
channelModel->SetAttribute ("Frequency", DoubleValue (60.0e9));
|
||||
channelModel->SetAttribute ("Scenario", StringValue ("RMa"));
|
||||
channelModel->SetAttribute ("ChannelConditionModel", PointerValue (channelConditionModel));
|
||||
channelModel->SetAttribute ("UpdatePeriod", TimeValue (MilliSeconds (updatePeriodMs-1)));
|
||||
|
||||
// create the tx and rx 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 tx and rx mobility models and set their positions
|
||||
Ptr<MobilityModel> txMob = CreateObject<ConstantPositionMobilityModel> ();
|
||||
txMob->SetPosition (Vector (0.0,0.0,10.0));
|
||||
Ptr<MobilityModel> rxMob = CreateObject<ConstantPositionMobilityModel> ();
|
||||
rxMob->SetPosition (Vector (100.0,0.0,10.0));
|
||||
|
||||
// associate the nodes and the mobility models
|
||||
nodes.Get (0)->AggregateObject (txMob);
|
||||
nodes.Get (1)->AggregateObject (rxMob);
|
||||
|
||||
// create the tx and rx antennas and set the their dimensions
|
||||
Ptr<ThreeGppAntennaArrayModel> txAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (txAntennaElements [0]), "NumRows", UintegerValue (txAntennaElements [1]), "IsotropicElements", BooleanValue (true));
|
||||
Ptr<ThreeGppAntennaArrayModel> rxAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (rxAntennaElements [0]), "NumRows", UintegerValue (rxAntennaElements [1]), "IsotropicElements", BooleanValue (true));
|
||||
|
||||
// generate the channel matrix
|
||||
Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> channelMatrix = channelModel->GetChannel (txMob, rxMob, txAntenna, rxAntenna);
|
||||
|
||||
// check the channel matrix dimensions
|
||||
NS_TEST_ASSERT_MSG_EQ (channelMatrix->m_channel.at (0).size (), txAntennaElements [0] * txAntennaElements [1], "The second dimension of H should be equal to the number of tx antenna elements");
|
||||
NS_TEST_ASSERT_MSG_EQ (channelMatrix->m_channel.size (), rxAntennaElements [0] * rxAntennaElements [1], "The first dimension of H should be equal to the number of rx antenna elements");
|
||||
|
||||
// test if the channel matrix is correctly generated
|
||||
uint16_t numIt = 1000;
|
||||
for (uint16_t i = 0; i < numIt; i++)
|
||||
{
|
||||
Simulator::Schedule (MilliSeconds (updatePeriodMs * i), &ThreeGppChannelMatrixComputationTest::DoComputeNorm, this, channelModel, txMob, rxMob, txAntenna, rxAntenna);
|
||||
}
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
// compute the sample mean
|
||||
double sampleMean = 0;
|
||||
for (auto i : m_normVector)
|
||||
{
|
||||
sampleMean += i;
|
||||
}
|
||||
sampleMean /= numIt;
|
||||
|
||||
// compute the sample standard deviation
|
||||
double sampleStd = 0;
|
||||
for (auto i : m_normVector)
|
||||
{
|
||||
sampleStd += ((i - sampleMean) * (i - sampleMean));
|
||||
}
|
||||
sampleStd = std::sqrt (sampleStd / (numIt - 1));
|
||||
|
||||
// perform the one sample t-test with a significance level of 0.05 to test
|
||||
// the hypothesis "E [|H|^2] = M*N, where |H| indicates the Frobenius norm of
|
||||
// H, M is the number of transmit antenna elements, and N is the number of
|
||||
// the receive antenna elements"
|
||||
double t = (sampleMean - txAntennaElements [0] * txAntennaElements [1] * rxAntennaElements [0] * rxAntennaElements [1]) / (sampleMean / std::sqrt (numIt));
|
||||
|
||||
// Using a significance level of 0.05, we reject the null hypothesis if |t| is
|
||||
// greater than the critical value from a t-distribution with df = numIt-1
|
||||
NS_TEST_ASSERT_MSG_EQ_TOL (std::abs (t), 0, 1.65, "We reject the hypothesis E[|H|^2] = M*N with a significance level of 0.05");
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case for the ThreeGppChannelModel class.
|
||||
* It checks if the channel realizations are correctly updated during the
|
||||
* simulation.
|
||||
*/
|
||||
class ThreeGppChannelMatrixUpdateTest : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppChannelMatrixUpdateTest ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreeGppChannelMatrixUpdateTest ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Build the test scenario
|
||||
*/
|
||||
virtual void DoRun (void);
|
||||
|
||||
/**
|
||||
* This method is used to schedule the channel matrix computation at different
|
||||
* time instants and to check if it correctly updated
|
||||
* \param channelModel the ThreeGppChannelModel object used to generate the channel matrix
|
||||
* \param txMob the mobility model of the first node
|
||||
* \param rxMob the mobility model of the second node
|
||||
* \param txAntenna the antenna object associated to the first node
|
||||
* \param rxAntenna the antenna object associated to the second node
|
||||
* \param update whether if the channel matrix should be updated or not
|
||||
*/
|
||||
void DoGetChannel (Ptr<ThreeGppChannelModel> channelModel, Ptr<MobilityModel> txMob, Ptr<MobilityModel> rxMob, Ptr<ThreeGppAntennaArrayModel> txAntenna, Ptr<ThreeGppAntennaArrayModel> rxAntenna, bool update);
|
||||
|
||||
Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> m_currentChannel; //!< used by DoGetChannel to store the current channel matrix
|
||||
};
|
||||
|
||||
ThreeGppChannelMatrixUpdateTest::ThreeGppChannelMatrixUpdateTest ()
|
||||
: TestCase ("Check if the channel realizations are correctly updated during the simulation")
|
||||
{
|
||||
}
|
||||
|
||||
ThreeGppChannelMatrixUpdateTest::~ThreeGppChannelMatrixUpdateTest ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppChannelMatrixUpdateTest::DoGetChannel (Ptr<ThreeGppChannelModel> channelModel, Ptr<MobilityModel> txMob, Ptr<MobilityModel> rxMob, Ptr<ThreeGppAntennaArrayModel> txAntenna, Ptr<ThreeGppAntennaArrayModel> rxAntenna, bool update)
|
||||
{
|
||||
// retrieve the channel matrix
|
||||
Ptr<const ThreeGppChannelModel::ThreeGppChannelMatrix> channelMatrix = channelModel->GetChannel (txMob, rxMob, txAntenna, rxAntenna);
|
||||
|
||||
if (m_currentChannel == 0)
|
||||
{
|
||||
// this is the first time we compute the channel matrix, we initialize
|
||||
// m_currentChannel
|
||||
m_currentChannel = channelMatrix;
|
||||
}
|
||||
else
|
||||
{
|
||||
// compare the old and the new channel matrices
|
||||
NS_TEST_ASSERT_MSG_EQ ((m_currentChannel != channelMatrix), update, Simulator::Now ().GetMilliSeconds () << " The channel matrix is not correctly updated");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppChannelMatrixUpdateTest::DoRun (void)
|
||||
{
|
||||
// Build the scenario for the test
|
||||
|
||||
uint8_t txAntennaElements[] {2, 2}; // tx antenna dimensions
|
||||
uint8_t rxAntennaElements[] {4, 4}; // rx antenna dimensions
|
||||
uint32_t updatePeriodMs = 100; // update period in ms
|
||||
|
||||
// create the channel condition model
|
||||
Ptr<ChannelConditionModel> channelConditionModel = CreateObject<AlwaysLosChannelConditionModel> ();
|
||||
|
||||
// create the ThreeGppChannelModel object used to generate the channel matrix
|
||||
Ptr<ThreeGppChannelModel> channelModel = CreateObject<ThreeGppChannelModel> ();
|
||||
channelModel->SetAttribute ("Frequency", DoubleValue (60.0e9));
|
||||
channelModel->SetAttribute ("Scenario", StringValue ("UMa"));
|
||||
channelModel->SetAttribute ("ChannelConditionModel", PointerValue (channelConditionModel));
|
||||
channelModel->SetAttribute ("UpdatePeriod", TimeValue (MilliSeconds (updatePeriodMs)));
|
||||
|
||||
// create the tx and rx 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 tx and rx mobility models and set their positions
|
||||
Ptr<MobilityModel> txMob = CreateObject<ConstantPositionMobilityModel> ();
|
||||
txMob->SetPosition (Vector (0.0,0.0,10.0));
|
||||
Ptr<MobilityModel> rxMob = CreateObject<ConstantPositionMobilityModel> ();
|
||||
rxMob->SetPosition (Vector (100.0,0.0,1.6));
|
||||
|
||||
// associate the nodes and the mobility models
|
||||
nodes.Get (0)->AggregateObject (txMob);
|
||||
nodes.Get (1)->AggregateObject (rxMob);
|
||||
|
||||
// create the tx and rx antennas and set the their dimensions
|
||||
Ptr<ThreeGppAntennaArrayModel> txAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (txAntennaElements [0]), "NumRows", UintegerValue (txAntennaElements [1]), "IsotropicElements", BooleanValue (true));
|
||||
Ptr<ThreeGppAntennaArrayModel> rxAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (rxAntennaElements [0]), "NumRows", UintegerValue (rxAntennaElements [1]), "IsotropicElements", BooleanValue (true));
|
||||
|
||||
// check if the channel matrix is correctly updated
|
||||
|
||||
// compute the channel matrix for the first time
|
||||
uint32_t firstTimeMs = 1; // time instant at which the channel matrix is generated for the first time
|
||||
Simulator::Schedule (MilliSeconds (firstTimeMs), &ThreeGppChannelMatrixUpdateTest::DoGetChannel, this, channelModel, txMob, rxMob, txAntenna, rxAntenna, true);
|
||||
|
||||
// call GetChannel before the update period is exceeded, the channel matrix
|
||||
// should not be updated
|
||||
Simulator::Schedule (MilliSeconds (firstTimeMs + updatePeriodMs / 2), &ThreeGppChannelMatrixUpdateTest::DoGetChannel, this, channelModel, txMob, rxMob, txAntenna, rxAntenna, false);
|
||||
|
||||
// call GetChannel when the update period is exceeded, the channel matrix
|
||||
// should be recomputed
|
||||
Simulator::Schedule (MilliSeconds (firstTimeMs + updatePeriodMs + 1), &ThreeGppChannelMatrixUpdateTest::DoGetChannel, this, channelModel, txMob, rxMob, txAntenna, rxAntenna, true);
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case for the ThreeGppSpectrumPropagationLossModelTest class.
|
||||
* 1) checks if the long term components for the direct and the reverse link
|
||||
* are the same
|
||||
* 2) checks if the long term component is updated when changing the beamforming
|
||||
* vectors
|
||||
* 3) checks if the long term is updated when changing the channel matrix
|
||||
*/
|
||||
class ThreeGppSpectrumPropagationLossModelTest : public TestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppSpectrumPropagationLossModelTest ();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreeGppSpectrumPropagationLossModelTest ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Build the test scenario
|
||||
*/
|
||||
virtual void DoRun (void);
|
||||
|
||||
/**
|
||||
* Points the beam of thisDevice towards otherDevice
|
||||
* \param thisDevice the device to configure
|
||||
* \param thisAntenna the antenna object associated to thisDevice
|
||||
* \param otherDevice the device to communicate with
|
||||
* \param otherAntenna the antenna object associated to otherDevice
|
||||
*/
|
||||
void DoBeamforming (Ptr<NetDevice> thisDevice, Ptr<ThreeGppAntennaArrayModel> thisAntenna, Ptr<NetDevice> otherDevice, Ptr<ThreeGppAntennaArrayModel> otherAntenna);
|
||||
|
||||
/**
|
||||
* Test of the long term component is correctly updated when the channel
|
||||
* matrix is recomputed
|
||||
* \param lossModel the ThreeGppSpectrumPropagationLossModel object used to
|
||||
* compute the rx PSD
|
||||
* \param txPsd the PSD of the transmitted signal
|
||||
* \param txMob the mobility model of the tx device
|
||||
* \param rxMob the mobility model of the rx device
|
||||
* \param rxPsdOld the previously received PSD
|
||||
*/
|
||||
void CheckLongTermUpdate (Ptr<ThreeGppSpectrumPropagationLossModel> lossModel, Ptr<SpectrumValue> txPsd, Ptr<MobilityModel> txMob, Ptr<MobilityModel> rxMob, Ptr<SpectrumValue> rxPsdOld);
|
||||
|
||||
/**
|
||||
* Checks if two PSDs are equal
|
||||
* \param first the first PSD
|
||||
* \param second the second PSD
|
||||
* \return true if first and second are equal, false otherwise
|
||||
*/
|
||||
static bool ArePsdEqual (Ptr<SpectrumValue> first, Ptr<SpectrumValue> second);
|
||||
};
|
||||
|
||||
ThreeGppSpectrumPropagationLossModelTest::ThreeGppSpectrumPropagationLossModelTest ()
|
||||
: TestCase ("Test case for the ThreeGppSpectrumPropagationLossModel class")
|
||||
{
|
||||
}
|
||||
|
||||
ThreeGppSpectrumPropagationLossModelTest::~ThreeGppSpectrumPropagationLossModelTest ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppSpectrumPropagationLossModelTest::DoBeamforming (Ptr<NetDevice> thisDevice, Ptr<ThreeGppAntennaArrayModel> thisAntenna, Ptr<NetDevice> otherDevice, Ptr<ThreeGppAntennaArrayModel> otherAntenna)
|
||||
{
|
||||
uint8_t noPlane = 1;
|
||||
ThreeGppAntennaArrayModel::ComplexVector antennaWeights;
|
||||
|
||||
Vector aPos = thisDevice->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
|
||||
Vector bPos = otherDevice->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
|
||||
|
||||
Angles completeAngle (bPos,aPos);
|
||||
|
||||
double posX = bPos.x - aPos.x;
|
||||
double phiAngle = atan ((bPos.y - aPos.y) / posX);
|
||||
|
||||
if (posX < 0)
|
||||
{
|
||||
phiAngle = phiAngle + M_PI;
|
||||
}
|
||||
if (phiAngle < 0)
|
||||
{
|
||||
phiAngle = phiAngle + 2 * M_PI;
|
||||
}
|
||||
|
||||
double hAngleRadian = fmod ((phiAngle + (M_PI / noPlane)),2 * M_PI / noPlane) - (M_PI / noPlane);
|
||||
double vAngleRadian = completeAngle.theta;
|
||||
|
||||
int totNoArrayElements = thisAntenna->GetNumberOfElements ();
|
||||
double power = 1 / sqrt (totNoArrayElements);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
thisAntenna->SetBeamformingVector (antennaWeights);
|
||||
}
|
||||
|
||||
bool
|
||||
ThreeGppSpectrumPropagationLossModelTest::ArePsdEqual (Ptr<SpectrumValue> first, Ptr<SpectrumValue> second)
|
||||
{
|
||||
bool ret = true;
|
||||
for (uint8_t i = 0; i < first->GetSpectrumModel ()->GetNumBands (); i++)
|
||||
{
|
||||
if ((*first) [i] != (*second) [i])
|
||||
{
|
||||
ret = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppSpectrumPropagationLossModelTest::CheckLongTermUpdate (Ptr<ThreeGppSpectrumPropagationLossModel> lossModel, Ptr<SpectrumValue> txPsd, Ptr<MobilityModel> txMob, Ptr<MobilityModel> rxMob, Ptr<SpectrumValue> rxPsdOld)
|
||||
{
|
||||
Ptr<SpectrumValue> rxPsdNew = lossModel->DoCalcRxPowerSpectralDensity (txPsd, txMob, rxMob);
|
||||
NS_TEST_ASSERT_MSG_EQ (ArePsdEqual (rxPsdOld, rxPsdNew), false, "The long term is not updated when the channel matrix is recomputed");
|
||||
}
|
||||
|
||||
void
|
||||
ThreeGppSpectrumPropagationLossModelTest::DoRun ()
|
||||
{
|
||||
// Build the scenario for the test
|
||||
Config::SetDefault ("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue (MilliSeconds (100)));
|
||||
|
||||
uint8_t txAntennaElements[] {4, 4}; // tx antenna dimensions
|
||||
uint8_t rxAntennaElements[] {4, 4}; // rx antenna dimensions
|
||||
|
||||
// create the ChannelConditionModel object to be used to retrieve the
|
||||
// channel condition
|
||||
Ptr<ChannelConditionModel> condModel = CreateObject<AlwaysLosChannelConditionModel> ();
|
||||
|
||||
// create the ThreeGppSpectrumPropagationLossModel object, set frequency,
|
||||
// scenario and channel condition model to be used
|
||||
Ptr<ThreeGppSpectrumPropagationLossModel> lossModel = CreateObject<ThreeGppSpectrumPropagationLossModel> ();
|
||||
lossModel->SetChannelModelAttribute ("Frequency", DoubleValue(2.4e9));
|
||||
lossModel->SetChannelModelAttribute ("Scenario", StringValue("UMa"));
|
||||
lossModel->SetChannelModelAttribute ("ChannelConditionModel", PointerValue (condModel)); // create the ThreeGppChannelModel object used to generate the channel matrix
|
||||
|
||||
// create the tx and rx 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 tx and rx mobility models and set their positions
|
||||
Ptr<MobilityModel> txMob = CreateObject<ConstantPositionMobilityModel> ();
|
||||
txMob->SetPosition (Vector (0.0,0.0,10.0));
|
||||
Ptr<MobilityModel> rxMob = CreateObject<ConstantPositionMobilityModel> ();
|
||||
rxMob->SetPosition (Vector (15.0,0.0,10.0)); // in this position the channel condition is always LOS
|
||||
|
||||
// associate the nodes and the mobility models
|
||||
nodes.Get (0)->AggregateObject (txMob);
|
||||
nodes.Get (1)->AggregateObject (rxMob);
|
||||
|
||||
// create the tx and rx antennas and set the their dimensions
|
||||
Ptr<ThreeGppAntennaArrayModel> txAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (txAntennaElements [0]), "NumRows", UintegerValue (txAntennaElements [1]));
|
||||
Ptr<ThreeGppAntennaArrayModel> rxAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (rxAntennaElements [0]), "NumRows", UintegerValue (rxAntennaElements [1]));
|
||||
|
||||
// initialize ThreeGppSpectrumPropagationLossModel
|
||||
lossModel->AddDevice (txDev, txAntenna);
|
||||
lossModel->AddDevice (rxDev, rxAntenna);
|
||||
|
||||
// set the beamforming vectors
|
||||
DoBeamforming (txDev, txAntenna, rxDev, rxAntenna);
|
||||
DoBeamforming (rxDev, rxAntenna, txDev, txAntenna);
|
||||
|
||||
// create the tx psd
|
||||
WifiSpectrumValue5MhzFactory sf;
|
||||
double txPower = 0.1; // Watts
|
||||
uint32_t channelNumber = 1;
|
||||
Ptr<SpectrumValue> txPsd = sf.CreateTxPowerSpectralDensity (txPower, channelNumber);
|
||||
|
||||
// compute the rx psd
|
||||
Ptr<SpectrumValue> rxPsdOld = lossModel->DoCalcRxPowerSpectralDensity (txPsd, txMob, rxMob);
|
||||
|
||||
// 1) check that the rx PSD is equal for both the direct and the reverse channel
|
||||
Ptr<SpectrumValue> rxPsdNew = lossModel->DoCalcRxPowerSpectralDensity (txPsd, rxMob, txMob);
|
||||
NS_TEST_ASSERT_MSG_EQ (ArePsdEqual (rxPsdOld, rxPsdNew), true, "The long term for the direct and the reverse channel are different");
|
||||
|
||||
// 2) check if the long term is updated when changing the BF vector
|
||||
// change the position of the rx device and recompute the beamforming vectors
|
||||
rxMob->SetPosition (Vector (10.0, 5.0, 10.0));
|
||||
ThreeGppAntennaArrayModel::ComplexVector txBfVector = txAntenna->GetBeamformingVector ();
|
||||
txBfVector [0] = std::complex<double> (0.0, 0.0);
|
||||
txAntenna->SetBeamformingVector (txBfVector);
|
||||
|
||||
rxPsdNew = lossModel->DoCalcRxPowerSpectralDensity (txPsd, rxMob, txMob);
|
||||
NS_TEST_ASSERT_MSG_EQ (ArePsdEqual (rxPsdOld, rxPsdNew), false, "Changing the BF vectors the rx PSD does not change");
|
||||
|
||||
// update rxPsdOld
|
||||
rxPsdOld = rxPsdNew;
|
||||
|
||||
// 3) check if the long term is updated when the channel matrix is recomputed
|
||||
Simulator::Schedule (MilliSeconds (101), &ThreeGppSpectrumPropagationLossModelTest::CheckLongTermUpdate, this, lossModel, txPsd, txMob, rxMob, rxPsdOld);
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup spectrum
|
||||
*
|
||||
* Test suite for the ThreeGppChannelModel class
|
||||
*/
|
||||
class ThreeGppChannelTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreeGppChannelTestSuite ();
|
||||
};
|
||||
|
||||
ThreeGppChannelTestSuite::ThreeGppChannelTestSuite ()
|
||||
: TestSuite ("three-gpp-channel", UNIT)
|
||||
{
|
||||
AddTestCase (new ThreeGppChannelMatrixComputationTest, TestCase::QUICK);
|
||||
AddTestCase (new ThreeGppChannelMatrixUpdateTest, TestCase::QUICK);
|
||||
AddTestCase (new ThreeGppSpectrumPropagationLossModelTest, TestCase::QUICK);
|
||||
}
|
||||
|
||||
static ThreeGppChannelTestSuite myTestSuite;
|
||||
@@ -12,13 +12,13 @@ def build(bld):
|
||||
'model/friis-spectrum-propagation-loss.cc',
|
||||
'model/constant-spectrum-propagation-loss.cc',
|
||||
'model/spectrum-phy.cc',
|
||||
'model/spectrum-channel.cc',
|
||||
'model/spectrum-channel.cc',
|
||||
'model/single-model-spectrum-channel.cc',
|
||||
'model/multi-model-spectrum-channel.cc',
|
||||
'model/spectrum-interference.cc',
|
||||
'model/spectrum-error-model.cc',
|
||||
'model/spectrum-model-ism2400MHz-res1MHz.cc',
|
||||
'model/spectrum-model-300kHz-300GHz-log.cc',
|
||||
'model/spectrum-model-300kHz-300GHz-log.cc',
|
||||
'model/wifi-spectrum-value-helper.cc',
|
||||
'model/waveform-generator.cc',
|
||||
'model/spectrum-analyzer.cc',
|
||||
@@ -30,6 +30,8 @@ def build(bld):
|
||||
'model/microwave-oven-spectrum-value-helper.cc',
|
||||
'model/tv-spectrum-transmitter.cc',
|
||||
'model/trace-fading-loss-model.cc',
|
||||
'model/three-gpp-spectrum-propagation-loss-model.cc',
|
||||
'model/three-gpp-channel-model.cc',
|
||||
'helper/spectrum-helper.cc',
|
||||
'helper/adhoc-aloha-noack-ideal-phy-helper.cc',
|
||||
'helper/waveform-generator-helper.cc',
|
||||
@@ -45,8 +47,9 @@ def build(bld):
|
||||
'test/spectrum-waveform-generator-test.cc',
|
||||
'test/tv-helper-distribution-test.cc',
|
||||
'test/tv-spectrum-transmitter-test.cc',
|
||||
'test/three-gpp-channel-test-suite.cc',
|
||||
]
|
||||
|
||||
|
||||
headers = bld(features='ns3header')
|
||||
headers.module = 'spectrum'
|
||||
headers.source = [
|
||||
@@ -59,14 +62,14 @@ def build(bld):
|
||||
'model/constant-spectrum-propagation-loss.h',
|
||||
'model/spectrum-phy.h',
|
||||
'model/spectrum-channel.h',
|
||||
'model/single-model-spectrum-channel.h',
|
||||
'model/single-model-spectrum-channel.h',
|
||||
'model/multi-model-spectrum-channel.h',
|
||||
'model/spectrum-interference.h',
|
||||
'model/spectrum-error-model.h',
|
||||
'model/spectrum-model-ism2400MHz-res1MHz.h',
|
||||
'model/spectrum-model-300kHz-300GHz-log.h',
|
||||
'model/wifi-spectrum-value-helper.h',
|
||||
'model/waveform-generator.h',
|
||||
'model/waveform-generator.h',
|
||||
'model/spectrum-analyzer.h',
|
||||
'model/aloha-noack-mac-header.h',
|
||||
'model/aloha-noack-net-device.h',
|
||||
@@ -76,6 +79,8 @@ def build(bld):
|
||||
'model/microwave-oven-spectrum-value-helper.h',
|
||||
'model/tv-spectrum-transmitter.h',
|
||||
'model/trace-fading-loss-model.h',
|
||||
'model/three-gpp-spectrum-propagation-loss-model.h',
|
||||
'model/three-gpp-channel-model.h',
|
||||
'helper/spectrum-helper.h',
|
||||
'helper/adhoc-aloha-noack-ideal-phy-helper.h',
|
||||
'helper/waveform-generator-helper.h',
|
||||
|
||||
Reference in New Issue
Block a user