1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011, 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author: Manuel Requena <manuel.requena@cttc.es>
19  *         Nicola Baldo <nbaldo@cttc.es>
20  */
21 
22 #include "ns3/simulator.h"
23 #include "ns3/log.h"
24 #include "ns3/string.h"
25 #include "ns3/double.h"
26 #include "ns3/enum.h"
27 #include "ns3/boolean.h"
28 #include "ns3/test.h"
29 #include "ns3/mobility-helper.h"
30 #include "ns3/lte-helper.h"
31 
32 #include "ns3/lte-ue-phy.h"
33 #include "ns3/lte-ue-net-device.h"
34 #include "ns3/lte-enb-phy.h"
35 #include "ns3/lte-enb-net-device.h"
36 #include "ns3/ff-mac-scheduler.h"
37 
38 #include "ns3/lte-global-pathloss-database.h"
39 
40 #include <ns3/lte-chunk-processor.h>
41 
42 
43 using namespace ns3;
44 
45 NS_LOG_COMPONENT_DEFINE ("LteAntennaTest");
46 
47 
48 /**
49  * \ingroup lte-test
50  * \ingroup tests
51  *
52  * \brief Tests that the propagation model and the antenna parameters are
53  * generate the correct values. Different test cases are created by specifying different
54  * antenna configurations and it is tested if for the given information the pathloss
55  * value is as expected.
56  */
57 class LteEnbAntennaTestCase : public TestCase
58 {
59 public:
60   /**
61    * Build name string
62    * \param orientationDegrees the orientation in degrees
63    * \param beamwidthDegrees the beam width in degrees
64    * \param x position of UE
65    * \param y position of UE
66    * \returns the name string
67    */
68   static std::string BuildNameString (double orientationDegrees, double beamwidthDegrees, double x, double y);
69   /**
70    * Constructor
71    *
72    * \param orientationDegrees the orientation in degrees
73    * \param beamwidthDegrees the beam width in degrees
74    * \param x position of UE
75    * \param y position of UE
76    * \param antennaGainDb the antenna gain in dB
77    */
78   LteEnbAntennaTestCase (double orientationDegrees, double beamwidthDegrees, double x, double y, double antennaGainDb);
79   LteEnbAntennaTestCase ();
80   virtual ~LteEnbAntennaTestCase ();
81 
82 private:
83   virtual void DoRun (void);
84 
85   double m_orientationDegrees; ///< antenna orientation in degrees
86   double m_beamwidthDegrees; ///< antenna beamwidth in degrees
87   double m_x; ///< x position of the UE
88   double m_y; ///< y position of the UE
89   double m_antennaGainDb; ///< antenna gain in dB
90 };
91 
92 
93 
94 
BuildNameString(double orientationDegrees,double beamwidthDegrees,double x,double y)95 std::string LteEnbAntennaTestCase::BuildNameString (double orientationDegrees, double beamwidthDegrees, double x, double y)
96 {
97   std::ostringstream oss;
98   oss <<  "o=" << orientationDegrees
99       << ", bw=" << beamwidthDegrees
100       << ", x=" << x
101       << ", y=" << y;
102   return oss.str ();
103 }
104 
105 
LteEnbAntennaTestCase(double orientationDegrees,double beamwidthDegrees,double x,double y,double antennaGainDb)106 LteEnbAntennaTestCase::LteEnbAntennaTestCase (double orientationDegrees, double beamwidthDegrees, double x, double y, double antennaGainDb)
107   : TestCase (BuildNameString (orientationDegrees, beamwidthDegrees, x, y)),
108     m_orientationDegrees (orientationDegrees),
109     m_beamwidthDegrees (beamwidthDegrees),
110     m_x (x),
111     m_y (y),
112     m_antennaGainDb (antennaGainDb)
113 {
114   NS_LOG_FUNCTION (this);
115 }
116 
~LteEnbAntennaTestCase()117 LteEnbAntennaTestCase::~LteEnbAntennaTestCase ()
118 {
119 }
120 
121 void
DoRun(void)122 LteEnbAntennaTestCase::DoRun (void)
123 {
124   Config::Reset ();
125   Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
126   Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
127   Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
128 
129   //Disable Uplink Power Control
130   Config::SetDefault ("ns3::LteUePhy::EnableUplinkPowerControl", BooleanValue (false));
131 
132   Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
133 
134   // use 0dB Pathloss, since we are testing only the antenna gain
135   lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::ConstantSpectrumPropagationLossModel"));
136   lteHelper->SetPathlossModelAttribute ("Loss", DoubleValue (0.0));
137 
138   // Create Nodes: eNodeB and UE
139   NodeContainer enbNodes;
140   NodeContainer ueNodes;
141   enbNodes.Create (1);
142   ueNodes.Create (1);
143   NodeContainer allNodes = NodeContainer ( enbNodes, ueNodes );
144 
145   // Install Mobility Model
146   Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
147   positionAlloc->Add (Vector (0.0, 0.0, 0.0));  // eNB
148   positionAlloc->Add (Vector (m_x, m_y, 0.0));  // UE
149   MobilityHelper mobility;
150   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
151   mobility.SetPositionAllocator (positionAlloc);
152   mobility.Install (allNodes);
153 
154   // Create Devices and install them in the Nodes (eNB and UE)
155   NetDeviceContainer enbDevs;
156   NetDeviceContainer ueDevs;
157   lteHelper->SetSchedulerType ("ns3::RrFfMacScheduler");
158   lteHelper->SetSchedulerAttribute ("UlCqiFilter", EnumValue (FfMacScheduler::PUSCH_UL_CQI));
159   lteHelper->SetEnbAntennaModelType ("ns3::CosineAntennaModel");
160   lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (m_orientationDegrees));
161   lteHelper->SetEnbAntennaModelAttribute ("HorizontalBeamwidth", DoubleValue (m_beamwidthDegrees));
162   lteHelper->SetEnbAntennaModelAttribute ("MaxGain", DoubleValue (0.0));
163 
164   // set DL and UL bandwidth.
165   lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (25));
166   lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (25));
167 
168   enbDevs = lteHelper->InstallEnbDevice (enbNodes);
169   ueDevs = lteHelper->InstallUeDevice (ueNodes);
170 
171   // Attach a UE to a eNB
172   lteHelper->Attach (ueDevs, enbDevs.Get (0));
173 
174   // Activate the default EPS bearer
175   enum EpsBearer::Qci q = EpsBearer::NGBR_VIDEO_TCP_DEFAULT;
176   EpsBearer bearer (q);
177   lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
178 
179   // Use testing chunk processor in the PHY layer
180   // It will be used to test that the SNR is as intended
181   Ptr<LtePhy> uePhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
182   Ptr<LteChunkProcessor> testDlSinr = Create<LteChunkProcessor> ();
183   LteSpectrumValueCatcher dlSinrCatcher;
184   testDlSinr->AddCallback (MakeCallback (&LteSpectrumValueCatcher::ReportValue, &dlSinrCatcher));
185   uePhy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr);
186 
187   Ptr<LtePhy> enbphy = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
188   Ptr<LteChunkProcessor> testUlSinr = Create<LteChunkProcessor> ();
189   LteSpectrumValueCatcher ulSinrCatcher;
190   testUlSinr->AddCallback (MakeCallback (&LteSpectrumValueCatcher::ReportValue, &ulSinrCatcher));
191   enbphy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr);
192 
193 
194   // keep track of all path loss values in two centralized objects
195   DownlinkLteGlobalPathlossDatabase dlPathlossDb;
196   UplinkLteGlobalPathlossDatabase ulPathlossDb;
197   // we rely on the fact that LteHelper creates the DL channel object first, then the UL channel object,
198   // hence the former will have index 0 and the latter 1
199   Config::Connect ("/ChannelList/0/PathLoss",
200                    MakeCallback (&DownlinkLteGlobalPathlossDatabase::UpdatePathloss, &dlPathlossDb));
201   Config::Connect ("/ChannelList/1/PathLoss",
202                     MakeCallback (&UplinkLteGlobalPathlossDatabase::UpdatePathloss, &ulPathlossDb));
203 
204   Simulator::Stop (Seconds (0.035));
205   Simulator::Run ();
206 
207   const double enbTxPowerDbm = 30; // default eNB TX power over whole bandwidth
208   const double ueTxPowerDbm  = 10; // default UE TX power over whole bandwidth
209   const double ktDbm = -174;    // reference LTE noise PSD
210   const double noisePowerDbm = ktDbm + 10 * std::log10 (25 * 180000); // corresponds to kT*bandwidth in linear units
211   const double ueNoiseFigureDb = 9.0; // default UE noise figure
212   const double enbNoiseFigureDb = 5.0; // default eNB noise figure
213   double tolerance = (m_antennaGainDb != 0) ? std::abs (m_antennaGainDb) * 0.001 : 0.001;
214 
215   // first test with SINR from LteChunkProcessor
216   // this can only be done for not-too-bad SINR otherwise the measurement won't be available
217   double expectedSinrDl = enbTxPowerDbm + m_antennaGainDb - noisePowerDbm + ueNoiseFigureDb;
218   if (expectedSinrDl > 0)
219     {
220       double calculatedSinrDbDl = -INFINITY;
221       if (dlSinrCatcher.GetValue () != 0)
222         {
223           calculatedSinrDbDl = 10.0 * std::log10 (dlSinrCatcher.GetValue ()->operator[] (0));
224         }
225       // remember that propagation loss is 0dB
226       double calculatedAntennaGainDbDl = - (enbTxPowerDbm - calculatedSinrDbDl - noisePowerDbm - ueNoiseFigureDb);
227       NS_LOG_INFO ("expected " << m_antennaGainDb << " actual " << calculatedAntennaGainDbDl << " tol " << tolerance);
228       NS_TEST_ASSERT_MSG_EQ_TOL (calculatedAntennaGainDbDl, m_antennaGainDb, tolerance, "Wrong DL antenna gain!");
229     }
230   double expectedSinrUl = ueTxPowerDbm + m_antennaGainDb - noisePowerDbm + enbNoiseFigureDb;
231   if (expectedSinrUl > 0)
232     {
233       double calculatedSinrDbUl = -INFINITY;
234       if (ulSinrCatcher.GetValue () != 0)
235         {
236           calculatedSinrDbUl = 10.0 * std::log10 (ulSinrCatcher.GetValue ()->operator[] (0));
237         }
238       double calculatedAntennaGainDbUl = - (ueTxPowerDbm - calculatedSinrDbUl - noisePowerDbm - enbNoiseFigureDb);
239       NS_TEST_ASSERT_MSG_EQ_TOL (calculatedAntennaGainDbUl, m_antennaGainDb, tolerance, "Wrong UL antenna gain!");
240     }
241 
242 
243   // repeat the same tests with the LteGlobalPathlossDatabases
244   double measuredLossDl = dlPathlossDb.GetPathloss (1, 1);
245   NS_TEST_ASSERT_MSG_EQ_TOL (measuredLossDl, -m_antennaGainDb, tolerance, "Wrong DL loss!");
246   double measuredLossUl = ulPathlossDb.GetPathloss (1, 1);
247   NS_TEST_ASSERT_MSG_EQ_TOL (measuredLossUl, -m_antennaGainDb, tolerance, "Wrong UL loss!");
248 
249 
250   Simulator::Destroy ();
251 }
252 
253 
254 /**
255  * \ingroup lte-test
256  * \ingroup tests
257  *
258  * \brief Lte Enb Antenna Test Suite
259  */
260 class LteAntennaTestSuite : public TestSuite
261 {
262 public:
263   LteAntennaTestSuite ();
264 };
265 
266 
LteAntennaTestSuite()267 LteAntennaTestSuite::LteAntennaTestSuite ()
268   : TestSuite ("lte-antenna", SYSTEM)
269 {
270   NS_LOG_FUNCTION (this);
271 
272   //                                      orientation beamwidth     x            y         gain
273   AddTestCase (new LteEnbAntennaTestCase (       0.0,     90.0,    1.0,          0.0,       0.0), TestCase::QUICK);
274   AddTestCase (new LteEnbAntennaTestCase (       0.0,     90.0,    1.0,          1.0,      -3.0), TestCase::QUICK);
275   AddTestCase (new LteEnbAntennaTestCase (       0.0,     90.0,    1.0,         -1.0,      -3.0), TestCase::QUICK);
276   AddTestCase (new LteEnbAntennaTestCase (       0.0,     90.0,   -1.0,         -1.0,   -36.396), TestCase::QUICK);
277   AddTestCase (new LteEnbAntennaTestCase (       0.0,     90.0,   -1.0,         -0.0,   -1414.6), TestCase::QUICK);
278   AddTestCase (new LteEnbAntennaTestCase (       0.0,     90.0,   -1.0,          1.0,   -36.396), TestCase::QUICK);
279   AddTestCase (new LteEnbAntennaTestCase (      45.0,     90.0,    1.0,          1.0,       0.0), TestCase::QUICK);
280   AddTestCase (new LteEnbAntennaTestCase (     -45.0,     90.0,    1.0,         -1.0,       0.0), TestCase::QUICK);
281   AddTestCase (new LteEnbAntennaTestCase (      90.0,     90.0,    1.0,          1.0,      -3.0), TestCase::QUICK);
282   AddTestCase (new LteEnbAntennaTestCase (     -90.0,     90.0,    1.0,         -1.0,      -3.0), TestCase::QUICK);
283 
284   AddTestCase (new LteEnbAntennaTestCase (       0.0,    120.0,    1.0,          0.0,       0.0), TestCase::QUICK);
285   AddTestCase (new LteEnbAntennaTestCase (       0.0,    120.0,    0.5,  sin(M_PI/3),      -3.0), TestCase::QUICK);
286   AddTestCase (new LteEnbAntennaTestCase (       0.0,    120.0,    0.5, -sin(M_PI/3),      -3.0), TestCase::QUICK);
287   AddTestCase (new LteEnbAntennaTestCase (       0.0,    120.0,   -1.0,         -2.0,   -13.410), TestCase::QUICK);
288   AddTestCase (new LteEnbAntennaTestCase (       0.0,    120.0,   -1.0,          1.0,   -20.034), TestCase::QUICK);
289   AddTestCase (new LteEnbAntennaTestCase (      60.0,    120.0,    0.5,  sin(M_PI/3),       0.0), TestCase::QUICK);
290   AddTestCase (new LteEnbAntennaTestCase (     -60.0,    120.0,    0.5, -sin(M_PI/3),       0.0), TestCase::QUICK);
291   AddTestCase (new LteEnbAntennaTestCase (     -60.0,    120.0,    0.5, -sin(M_PI/3),       0.0), TestCase::QUICK);
292   AddTestCase (new LteEnbAntennaTestCase (    -120.0,    120.0,   -0.5, -sin(M_PI/3),       0.0), TestCase::QUICK);
293   AddTestCase (new LteEnbAntennaTestCase (    -120.0,    120.0,    0.5, -sin(M_PI/3),      -3.0), TestCase::QUICK);
294   AddTestCase (new LteEnbAntennaTestCase (    -120.0,    120.0,     -1,            0,      -3.0), TestCase::QUICK);
295   AddTestCase (new LteEnbAntennaTestCase (    -120.0,    120.0,     -1,            2,   -15.578), TestCase::QUICK);
296   AddTestCase (new LteEnbAntennaTestCase (    -120.0,    120.0,      1,            0,   -14.457), TestCase::QUICK);
297   AddTestCase (new LteEnbAntennaTestCase (    -120.0,    120.0,      1,            2,   -73.154), TestCase::QUICK);
298   AddTestCase (new LteEnbAntennaTestCase (    -120.0,    120.0,      1,         -0.1,   -12.754), TestCase::QUICK);
299 
300 
301 }
302 
303 static LteAntennaTestSuite lteAntennaTestSuite;
304