diff --git a/src/antenna/doc/source/antenna-design.rst b/src/antenna/doc/source/antenna-design.rst index 2b28b28c5..e526c654f 100644 --- a/src/antenna/doc/source/antenna-design.rst +++ b/src/antenna/doc/source/antenna-design.rst @@ -88,6 +88,23 @@ practice alter the effective beamwidth of the resulting radiation pattern. + +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-092042]_ 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. + + + References ++++++++++ @@ -96,3 +113,13 @@ References .. [Chunjian] Li Chunjian, "Efficient Antenna Patterns for Three-Sector WCDMA Systems", Master of Science Thesis, Chalmers University of Technology, Göteborg, Sweden, 2003 + +.. [Calcev] George Calcev and Matt Dillon, "Antenna Tilt Control in + CDMA Networks", in Proc. of the 2nd Annual International Wireless + Internet Conference (WICON), 2006 + +.. [R4-092042] 3GPP TSG RAN WG4 (Radio) Meeting #51, R4-092042, Simulation + assumptions and parameters for FDD HeNB RF requirements. + + + diff --git a/src/antenna/doc/source/antenna-testing.rst b/src/antenna/doc/source/antenna-testing.rst index 58e976726..e588861e9 100644 --- a/src/antenna/doc/source/antenna-testing.rst +++ b/src/antenna/doc/source/antenna-testing.rst @@ -54,6 +54,20 @@ values. +ParabolicAntennaModel +------------------ + +The unit test suite ``parabolic-antenna-model`` checks that the +``ParabolicAntennaModel`` class works properly. Several test cases are +provided that check for the antenna gain value calculated at different +directions and for different values of the orientation, the maximum attenuation +and the beamwidth. The reference gain is calculated by hand. Each +test case passes if the reference gain in dB is equal to the value returned +by ``ParabolicAntennaModel`` within a tolerance of 0.001, which accounts +for the approximation done for the calculation of the reference +values. + + diff --git a/src/antenna/model/cosine-antenna-model.h b/src/antenna/model/cosine-antenna-model.h index bb5796a44..ffca5f1a1 100644 --- a/src/antenna/model/cosine-antenna-model.h +++ b/src/antenna/model/cosine-antenna-model.h @@ -31,7 +31,7 @@ namespace ns3 { * * \brief Cosine Antenna Model * - * This class implements the cosine model as described in [1] + * This class implements the cosine model as described in: * * Li Chunjian, "Efficient Antenna Patterns for Three-Sector WCDMA Systems" * @@ -60,7 +60,7 @@ public: private: /** - * this is the variable "n" in [1] + * this is the variable "n" in the paper by Chunjian * */ double m_exponent; diff --git a/src/antenna/model/parabolic-antenna-model.cc b/src/antenna/model/parabolic-antenna-model.cc new file mode 100644 index 000000000..eb3169ab4 --- /dev/null +++ b/src/antenna/model/parabolic-antenna-model.cc @@ -0,0 +1,117 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2012 CTTC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Nicola Baldo + */ + + +#include +#include +#include + +#include "antenna-model.h" +#include "parabolic-antenna-model.h" + + +NS_LOG_COMPONENT_DEFINE ("ParabolicAntennaModel"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (ParabolicAntennaModel); + + +TypeId +ParabolicAntennaModel::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::ParabolicAntennaModel") + .SetParent () + .AddConstructor () + .AddAttribute ("Beamwidth", + "The 3dB beamwidth (degrees)", + DoubleValue (60), + MakeDoubleAccessor (&ParabolicAntennaModel::SetBeamwidth, + &ParabolicAntennaModel::GetBeamwidth), + MakeDoubleChecker (0, 180)) + .AddAttribute ("Orientation", + "The angle (degrees) that expresses the orientation of the antenna on the x-y plane relative to the x axis", + DoubleValue (0.0), + MakeDoubleAccessor (&ParabolicAntennaModel::SetOrientation, + &ParabolicAntennaModel::GetOrientation), + MakeDoubleChecker (-360, 360)) + .AddAttribute ("MaxAttenuation", + "The maximum attenuation (dB) of the antenna radiation pattern.", + DoubleValue (20.0), + MakeDoubleAccessor (&ParabolicAntennaModel::m_maxAttenuation), + MakeDoubleChecker ()) + ; + return tid; +} + +void +ParabolicAntennaModel::SetBeamwidth (double beamwidthDegrees) +{ + NS_LOG_FUNCTION (this << beamwidthDegrees); + m_beamwidthRadians = DegreesToRadians (beamwidthDegrees); +} + +double +ParabolicAntennaModel::GetBeamwidth () const +{ + return RadiansToDegrees (m_beamwidthRadians); +} + +void +ParabolicAntennaModel::SetOrientation (double orientationDegrees) +{ + NS_LOG_FUNCTION (this << orientationDegrees); + m_orientationRadians = DegreesToRadians (orientationDegrees); +} + +double +ParabolicAntennaModel::GetOrientation () const +{ + return RadiansToDegrees (m_orientationRadians); +} + +double +ParabolicAntennaModel::GetGainDb (Angles a) +{ + NS_LOG_FUNCTION (this << a); + // azimuth angle w.r.t. the reference system of the antenna + double phi = a.phi - m_orientationRadians; + + // make sure phi is in (-pi, pi] + while (phi <= -M_PI) + { + phi += M_PI+M_PI; + } + while (phi > M_PI) + { + phi -= M_PI+M_PI; + } + + NS_LOG_LOGIC ("phi = " << phi ); + + double gainDb = -std::min (12 * pow (phi / m_beamwidthRadians, 2), m_maxAttenuation); + + NS_LOG_LOGIC ("gain = " << gainDb); + return gainDb; +} + + +} + diff --git a/src/antenna/model/parabolic-antenna-model.h b/src/antenna/model/parabolic-antenna-model.h new file mode 100644 index 000000000..2fb624e25 --- /dev/null +++ b/src/antenna/model/parabolic-antenna-model.h @@ -0,0 +1,76 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2012 CTTC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Nicola Baldo + */ + +#ifndef PARABOLIC_ANTENNA_MODEL_H +#define PARABOLIC_ANTENNA_MODEL_H + + +#include +#include + +namespace ns3 { + +/** + * + * \brief Antenna model based on a parabolic approximation of the main lobe radiation pattern. + * + * This class implements the parabolic model as described in some 3GPP document, e.g., R4-092042 + * + * A similar model appears in + * + * George Calcev and Matt Dillon, "Antenna Tilt Control in CDMA Networks" + * in Proc. of the 2nd Annual International Wireless Internet Conference (WICON), 2006 + * + * though the latter addresses also the elevation plane, which the present model doesn't. + * + * + */ +class ParabolicAntennaModel : public AntennaModel +{ +public: + + // inherited from Object + static TypeId GetTypeId (); + + // inherited from AntennaModel + virtual double GetGainDb (Angles a); + + + // attribute getters/setters + void SetBeamwidth (double beamwidthDegrees); + double GetBeamwidth () const; + void SetOrientation (double orientationDegrees); + double GetOrientation () const; + +private: + + double m_beamwidthRadians; + + double m_orientationRadians; + + double m_maxAttenuation; +}; + + + +} // namespace ns3 + + +#endif // PARABOLIC_ANTENNA_MODEL_H diff --git a/src/antenna/test/test-parabolic-antenna.cc b/src/antenna/test/test-parabolic-antenna.cc new file mode 100644 index 000000000..33d8906e0 --- /dev/null +++ b/src/antenna/test/test-parabolic-antenna.cc @@ -0,0 +1,190 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011,12 CTTC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Nicola Baldo + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +NS_LOG_COMPONENT_DEFINE ("TestParabolicAntennaModel"); + +namespace ns3 { + +enum ParabolicAntennaModelGainTestCondition { + EQUAL = 0, + LESSTHAN = 1 +}; + +class ParabolicAntennaModelTestCase : public TestCase +{ +public: + static std::string BuildNameString (Angles a, double b, double o, double g); + ParabolicAntennaModelTestCase (Angles a, double b, double o, double g, double expectedGainDb, ParabolicAntennaModelGainTestCondition cond); + + +private: + virtual void DoRun (void); + + Angles m_a; + double m_b; + double m_o; + double m_g; + double m_expectedGain; + ParabolicAntennaModelGainTestCondition m_cond; +}; + +std::string ParabolicAntennaModelTestCase::BuildNameString (Angles a, double b, double o, double g) +{ + std::ostringstream oss; + oss << "theta=" << a.theta << " , phi=" << a.phi + << ", beamdwidth=" << b << "deg" + << ", orientation=" << o + << ", maxAttenuation=" << g << " dB"; + return oss.str (); +} + + +ParabolicAntennaModelTestCase::ParabolicAntennaModelTestCase (Angles a, double b, double o, double g, double expectedGainDb, ParabolicAntennaModelGainTestCondition cond) + : TestCase (BuildNameString (a, b, o, g)), + m_a (a), + m_b (b), + m_o (o), + m_g (g), + m_expectedGain (expectedGainDb), + m_cond (cond) +{ +} + +void +ParabolicAntennaModelTestCase::DoRun () +{ + NS_LOG_FUNCTION (this << BuildNameString (m_a, m_b, m_o, m_g)); + + Ptr a = CreateObject (); + a->SetAttribute ("Beamwidth", DoubleValue (m_b)); + a->SetAttribute ("Orientation", DoubleValue (m_o)); + a->SetAttribute ("MaxAttenuation", DoubleValue (m_g)); + double actualGain = a->GetGainDb (m_a); + switch (m_cond) + { + case EQUAL: + NS_TEST_EXPECT_MSG_EQ_TOL (actualGain, m_expectedGain, 0.001, "wrong value of the radiation pattern"); + break; + case LESSTHAN: + NS_TEST_EXPECT_MSG_LT (actualGain, m_expectedGain, "gain higher than expected"); + break; + default: + break; + } +} + + + + +class ParabolicAntennaModelTestSuite : public TestSuite +{ +public: + ParabolicAntennaModelTestSuite (); +}; + +ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite () + : TestSuite ("parabolic-antenna-model", UNIT) +{ + + // with a 60 deg beamwidth, gain is -20dB at +-77.460 degrees from boresight + // phi, theta, beamwidth, orientation, maxAttn, expectedGain, condition + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (0), 0), 60, 0, 20, 0, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (30), 0), 60, 0, 20, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-30), 0), 60, 0, 20, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-90), 0), 60, 0, 20, -20, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (90), 0), 60, 0, 20, -20, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (100), 0), 60, 0, 20, -20, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (150), 0), 60, 0, 20, -20, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (180), 0), 60, 0, 20, -20, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-100), 0), 60, 0, 20, -20, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-150), 0), 60, 0, 20, -20, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-180), 0), 60, 0, 20, -20, EQUAL)); + + // with a 60 deg beamwidth, gain is -10dB at +-54.772 degrees from boresight + // test positive orientation + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (60), 0), 60, 60, 10, 0, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (90), 0), 60, 60, 10, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (30), 0), 60, 60, 10, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-30), 0), 60, 60, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (150), 0), 60, 60, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (160), 0), 60, 60, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (210), 0), 60, 60, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (240), 0), 60, 60, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-40), 0), 60, 60, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-90), 0), 60, 60, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-120), 0), 60, 60, 10, -10, EQUAL)); + + // test negative orientation and different beamwidths + // with a 80 deg beamwidth, gain is -20dB at +- 73.030 degrees from boresight + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-150), 0), 80, -150, 10, 0, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-110), 0), 80, -150, 10, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-190), 0), 80, -150, 10, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-70), 0), 80, -150, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (92), 0), 80, -150, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-30), 0), 80, -150, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (0), 0), 80, -150, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (60), 0), 80, -150, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (90), 0), 80, -150, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (30), 0), 80, -150, 10, -10, EQUAL)); + + + + // test elevation angle + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (0), 2), 60, 0, 20, 0, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (30), 2), 60, 0, 20, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-30), 2), 60, 0, 20, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-90), 2), 60, 0, 20, -20, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-180), 2), 60, 0, 20, -20, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (60), -3), 60, 60, 20, 0, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (90), -3), 60, 60, 20, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (30), -3), 60, 60, 20, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-120), -3), 60, 60, 20, -20, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-150), -3), 100, -150, 10, 0, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-100), -3), 100, -150, 10, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-200), -3), 100, -150, 10, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-30), -3), 100, -150, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (90), 9.5), 100, -150, 10, -10, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (0), 9.5), 60, 0, 20, 0, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (30), 9.5), 60, 0, 20, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-30), 9.5), 60, 0, 20, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (100), 9.5), 60, 0, 20, -20, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-150), 9.5), 100, -150, 30, 0, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-100), 9.5), 100, -150, 30, -3, EQUAL)); + AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-200), 9.5), 100, -150, 30, -3, EQUAL)); + +}; + +static ParabolicAntennaModelTestSuite staticParabolicAntennaModelTestSuiteInstance; + + + + +} // namespace ns3 diff --git a/src/antenna/wscript b/src/antenna/wscript index 78a5da695..1312bfc85 100644 --- a/src/antenna/wscript +++ b/src/antenna/wscript @@ -9,6 +9,7 @@ def build(bld): 'model/antenna-model.cc', 'model/isotropic-antenna-model.cc', 'model/cosine-antenna-model.cc', + 'model/parabolic-antenna-model.cc', ] module_test = bld.create_ns3_module_test_library('antenna') @@ -17,6 +18,7 @@ def build(bld): 'test/test-degrees-radians.cc', 'test/test-isotropic-antenna.cc', 'test/test-cosine-antenna.cc', + 'test/test-parabolic-antenna.cc', ] headers = bld.new_task_gen(features=['ns3header']) @@ -26,6 +28,7 @@ def build(bld): 'model/antenna-model.h', 'model/isotropic-antenna-model.h', 'model/cosine-antenna-model.h', + 'model/parabolic-antenna-model.h', ]