A Discrete-Event Network Simulator
API
three-gpp-antenna-array-model.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2019 SIGNET Lab, Department of Information Engineering,
4 * University of Padova
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation;
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20 
22 #include "ns3/log.h"
23 #include "ns3/double.h"
24 #include "ns3/uinteger.h"
25 #include "ns3/boolean.h"
26 
27 namespace ns3 {
28 
29 NS_LOG_COMPONENT_DEFINE ("ThreeGppAntennaArrayModel");
30 
31 NS_OBJECT_ENSURE_REGISTERED (ThreeGppAntennaArrayModel);
32 
34 {
35  NS_LOG_FUNCTION (this);
36  m_isOmniTx = false;
37 }
38 
40 {
41  NS_LOG_FUNCTION (this);
42 }
43 
44 TypeId
46 {
47  static TypeId tid = TypeId ("ns3::ThreeGppAntennaArrayModel")
48  .SetParent<Object> ()
49  .AddConstructor<ThreeGppAntennaArrayModel> ()
50  .AddAttribute ("AntennaHorizontalSpacing",
51  "Horizontal spacing between antenna elements, in multiples of wave length",
52  DoubleValue (0.5),
54  MakeDoubleChecker<double> ())
55  .AddAttribute ("AntennaVerticalSpacing",
56  "Vertical spacing between antenna elements, in multiples of wave length",
57  DoubleValue (0.5),
59  MakeDoubleChecker<double> ())
60  .AddAttribute ("NumColumns",
61  "Horizontal size of the array",
62  UintegerValue (4),
64  MakeUintegerChecker<uint32_t> ())
65  .AddAttribute ("NumRows",
66  "Vertical size of the array",
67  UintegerValue (4),
69  MakeUintegerChecker<uint32_t> ())
70  .AddAttribute ("BearingAngle",
71  "The bearing angle in radians",
72  DoubleValue (0.0),
74  MakeDoubleChecker<double> (-M_PI, M_PI))
75  .AddAttribute ("DowntiltAngle",
76  "The downtilt angle in radians",
77  DoubleValue (0.0),
79  MakeDoubleChecker<double> (0, M_PI))
80  .AddAttribute ("ElementGain",
81  "Directional gain of an antenna element in dBi",
82  DoubleValue (4.97),
84  MakeDoubleChecker<double> (0, 8))
85  .AddAttribute ("IsotropicElements",
86  "If true, use an isotropic radiation pattern (for testing purposes)",
87  BooleanValue (false),
90  ;
91  return tid;
92 }
93 
94 bool
96 {
97  NS_LOG_FUNCTION (this);
98  return m_isOmniTx;
99 }
100 
101 void
103 {
104  NS_LOG_FUNCTION (this);
105  m_isOmniTx = true;
106 }
107 
108 void
110 {
111  NS_LOG_FUNCTION (this);
112  m_isOmniTx = false;
113  m_beamformingVector = beamformingVector;
114 }
115 
118 {
119  NS_LOG_FUNCTION (this);
120  return m_beamformingVector;
121 }
122 
123 std::pair<double, double>
125 {
126  NS_LOG_FUNCTION (this);
127 
128  // normalize phi (if needed)
129  a.phi = fmod (a.phi + M_PI, 2 * M_PI);
130  if (a.phi < 0)
131  a.phi += M_PI;
132  else
133  a.phi -= M_PI;
134 
135  NS_ASSERT_MSG (a.theta >= 0 && a.theta <= M_PI, "The vertical angle should be between 0 and M_PI");
136  NS_ASSERT_MSG (a.phi >= -M_PI && a.phi <= M_PI, "The horizontal angle should be between -M_PI and M_PI");
137 
138  // convert the theta and phi angles from GCS to LCS using eq. 7.1-7 and 7.1-8 in 3GPP TR 38.901
139  // NOTE we assume a fixed slant angle of 0 degrees
140  double thetaPrime = std::acos (cos (m_beta)*cos (a.theta) + sin (m_beta)*cos (a.phi-m_alpha)*sin (a.theta));
141  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)));
142  NS_LOG_DEBUG (a.theta << " " << thetaPrime << " " << a.phi << " " << phiPrime);
143 
144  double aPrimeDb = GetRadiationPattern (thetaPrime, phiPrime);
145  double aPrime = pow (10, aPrimeDb / 10); // convert to linear
146 
147  // compute psi using eq. 7.1-15 in 3GPP TR 38.901, assuming that the slant
148  // angle (gamma) is 0
149  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)));
150  NS_LOG_DEBUG ("psi " << psi);
151 
152  // compute the antenna element field pattern in the vertical polarization using
153  // eq. 7.3-4 in 3GPP TR 38.901
154  // NOTE we assume vertical polarization, hence the field pattern in the
155  // horizontal polarization is 0
156  double fieldThetaPrime = std::sqrt (aPrime);
157 
158  // convert the antenna element field pattern to GCS using eq. 7.1-11
159  // in 3GPP TR 38.901
160  double fieldTheta = cos (psi) * fieldThetaPrime;
161  double fieldPhi = sin (psi) * fieldThetaPrime;
162  NS_LOG_DEBUG (a.phi/M_PI*180 << " " << a.theta/M_PI*180 << " " << fieldTheta*fieldTheta + fieldPhi*fieldPhi);
163 
164  return std::make_pair (fieldPhi, fieldTheta);
165 }
166 
167 double
168 ThreeGppAntennaArrayModel::GetRadiationPattern (double thetaRadian, double phiRadian) const
169 {
170  if (m_isIsotropic)
171  {
172  return 0;
173  }
174 
175  // convert the angles in degrees
176  double thetaDeg = thetaRadian * 180 / M_PI;
177  double phiDeg = phiRadian * 180 / M_PI;
178  NS_ASSERT_MSG (thetaDeg >= 0 && thetaDeg <= 180, "the vertical angle should be the range of [0,180]");
179  NS_ASSERT_MSG (phiDeg >= -180 && phiDeg <= 180, "the horizontal angle should be the range of [-180,180]");
180 
181  // compute the radiation power pattern using equations in table 7.3-1 in
182  // 3GPP TR 38.901
183  double A_M = 30; // front-back ratio expressed in dB
184  double SLA = 30; // side-lobe level limit expressed in dB
185 
186  double A_v = -1 * std::min (SLA,12 * pow ((thetaDeg - 90) / 65,2)); // vertical cut of the radiation power pattern (dB)
187  double A_h = -1 * std::min (A_M,12 * pow (phiDeg / 65,2)); // horizontal cut of the radiation power pattern (dB)
188 
189  double A = m_gE - 1 * std::min (A_M,- A_v - A_h); // 3D radiation power pattern (dB)
190 
191  return A; // 3D radiation power pattern in dB
192 }
193 
194 Vector
196 {
197  NS_LOG_FUNCTION (this);
198 
199  // compute the element coordinates in the LCS
200  // assume the left bottom corner is (0,0,0), and the rectangular antenna array is on the y-z plane.
201  double xPrime = 0;
202  double yPrime = m_disH * (index % m_numColumns);
203  double zPrime = m_disV * floor (index / m_numColumns);
204 
205  // convert the coordinates to the GCS using the rotation matrix 7.1-4 in 3GPP
206  // TR 38.901
207  Vector loc;
208  loc.x = cos(m_alpha)*cos (m_beta)*xPrime - sin (m_alpha)*yPrime + cos (m_alpha)*sin (m_beta)*zPrime;
209  loc.y = sin (m_alpha)*cos(m_beta)*xPrime + cos (m_alpha)*yPrime + sin (m_alpha)*sin (m_beta)*zPrime;
210  loc.z = -sin (m_beta)*xPrime+cos(m_beta)*zPrime;
211  return loc;
212 }
213 
214 uint64_t
216 {
217  NS_LOG_FUNCTION (this);
218  return m_numRows * m_numColumns;
219 }
220 
221 } /* namespace ns3 */
virtual uint64_t GetNumberOfElements(void) const
Returns the number of antenna elements.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
AttributeValue implementation for Boolean.
Definition: boolean.h:36
std::vector< std::complex< double > > ComplexVector
type definition for complex vectors
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
double m_disH
antenna spacing in the horizontal direction in multiples of wave length
#define min(a, b)
Definition: 80211b.c:42
bool m_isOmniTx
true if the antenna is configured for omni transmissions
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:85
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
double theta
the inclination angle in radians
Definition: angles.h:117
virtual Vector GetElementLocation(uint64_t index) const
Returns the location of the antenna element with the specified index assuming the left bottom corner ...
double m_disV
antenna spacing in the vertical direction in multiples of wave length
Hold an unsigned integer type.
Definition: uinteger.h:44
virtual ~ThreeGppAntennaArrayModel(void)
Destructor.
double m_alpha
the bearing angle in radians
void SetBeamformingVector(const ComplexVector &beamformingVector)
Sets the beamforming vector to be used.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double m_gE
directional gain of a single antenna element (dBi)
ComplexVector m_beamformingVector
the beamforming vector in use
const ComplexVector & GetBeamformingVector(void) const
Returns the beamforming vector that is currently being used.
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: double.h:42
double m_beta
the downtilt angle in radians
bool IsOmniTx(void) const
Returns true if the antenna is configured for omnidirectional transmissions.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
double phi
the azimuth angle in radians
Definition: angles.h:111
double GetRadiationPattern(double vAngleRadian, double hAngleRadian) const
Returns the radiation power pattern of a single antenna element in dB, generated according to Table 7...
bool m_isIsotropic
if true, antenna elements are isotropic
void ChangeToOmniTx(void)
Change the antenna model to omnidirectional (ignoring the beams)
struct holding the azimuth and inclination angles of spherical coordinates.
Definition: angles.h:71
A base class which provides memory management and object aggregation.
Definition: object.h:87
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
std::pair< double, double > GetElementFieldPattern(Angles a) const
Returns the horizontal and vertical components of the antenna element field pattern at the specified ...