diff --git a/doc/models/Makefile b/doc/models/Makefile index 470cdc183..ce99b8324 100644 --- a/doc/models/Makefile +++ b/doc/models/Makefile @@ -17,6 +17,10 @@ SOURCES = \ source/internet-models.rst \ source/network.rst \ source/emulation-overview.rst \ + $(SRC)/antenna/doc/source/antenna.rst \ + $(SRC)/antenna/doc/source/antenna-design.rst \ + $(SRC)/antenna/doc/source/antenna-user.rst \ + $(SRC)/antenna/doc/source/antenna-testing.rst \ $(SRC)/aodv/doc/aodv.rst \ $(SRC)/applications/doc/applications.rst \ $(SRC)/bridge/doc/bridge.rst \ @@ -68,6 +72,7 @@ SOURCES = \ SOURCEFIGS = \ figures/testbed.dia \ figures/emulated-channel.dia \ + $(SRC)/antenna/doc/source/figures/antenna-coordinate-system.dia \ $(SRC)/network/doc/packet.dia \ $(SRC)/network/doc/node.dia \ $(SRC)/network/doc/buffer.dia \ @@ -91,6 +96,10 @@ SOURCEFIGS = \ $(SRC)/lte/doc/source/figures/epc-data-flow-ul.dia \ $(SRC)/lte/doc/source/figures/lte-arch-data-rrc-pdcp-rlc.dia \ $(SRC)/lte/doc/source/figures/lte-epc-e2e-data-protocol-stack.dia \ + $(SRC)/lte/doc/source/figures/MCS_2_test.eps \ + $(SRC)/lte/doc/source/figures/MCS_12_test.eps \ + $(SRC)/lte/doc/source/figures/MCS_14_test.eps \ + $(SRC)/lte/doc/source/figures/lena-dual-stripe.eps \ $(SRC)/lte/doc/source/figures/lte-mcs-index.eps \ $(SRC)/lte/doc/source/figures/lenaThrTestCase1.eps \ $(SRC)/lte/doc/source/figures/lenaThrTestCase2.eps \ @@ -106,16 +115,32 @@ SOURCEFIGS = \ $(SRC)/lte/doc/source/figures/lte-rlc-data-retx-dl.eps \ $(SRC)/lte/doc/source/figures/lte-rlc-data-txon-ul.eps \ $(SRC)/lte/doc/source/figures/lte-rlc-data-retx-ul.eps \ + $(SRC)/lte/doc/source/figures/fading_pedestrian.png \ $(SRC)/lte/doc/source/figures/fading_vehicular.png \ $(SRC)/lte/doc/source/figures/fading_urban_3kmph.png \ - $(SRC)/lte/doc/source/figures/fading_pedestrian.png \ + $(SRC)/lte/doc/source/figures/fading_pedestrian.pdf \ $(SRC)/lte/doc/source/figures/fading_vehicular.pdf \ $(SRC)/lte/doc/source/figures/fading_urban_3kmph.pdf \ - $(SRC)/lte/doc/source/figures/fading_pedestrian.pdf \ + $(SRC)/lte/doc/source/figures/MCS_1_4.pdf \ + $(SRC)/lte/doc/source/figures/MCS_1_4.png \ + $(SRC)/lte/doc/source/figures/MCS_5_8.pdf \ + $(SRC)/lte/doc/source/figures/MCS_5_8.png \ + $(SRC)/lte/doc/source/figures/MCS_9_12.pdf \ + $(SRC)/lte/doc/source/figures/MCS_9_12.png \ + $(SRC)/lte/doc/source/figures/MCS_13_16.pdf \ + $(SRC)/lte/doc/source/figures/MCS_13_16.png \ + $(SRC)/lte/doc/source/figures/MCS_17_20.pdf \ + $(SRC)/lte/doc/source/figures/MCS_17_20.png \ + $(SRC)/lte/doc/source/figures/MCS_21_24.pdf \ + $(SRC)/lte/doc/source/figures/MCS_21_24.png \ + $(SRC)/lte/doc/source/figures/MCS_25_27.pdf \ + $(SRC)/lte/doc/source/figures/MCS_25_27.png \ $(SRC)/lte/doc/source/figures/lte-phy-interference.png \ $(SRC)/lte/doc/source/figures/lte-phy-interference.pdf \ $(SRC)/lte/doc/source/figures/helpers.png \ $(SRC)/lte/doc/source/figures/helpers.pdf \ + $(SRC)/lte/doc/source/figures/miesm_scheme.pdf \ + $(SRC)/lte/doc/source/figures/miesm_scheme.png \ $(SRC)/uan/doc/auvmobility-classes.dia \ $(SRC)/stats/doc/Stat-framework-arch.png \ $(SRC)/stats/doc/Wifi-default.png \ @@ -131,6 +156,7 @@ IMAGES_EPS = \ $(FIGURES)/node.eps \ $(FIGURES)/buffer.eps \ $(FIGURES)/sockets-overview.eps \ + $(FIGURES)/antenna-coordinate-system.eps \ $(FIGURES)/internet-node-send.eps \ $(FIGURES)/internet-node-recv.eps \ $(FIGURES)/routing.eps \ @@ -150,6 +176,10 @@ IMAGES_EPS = \ $(FIGURES)/epc-data-flow-ul.eps \ $(FIGURES)/lte-arch-data-rrc-pdcp-rlc.eps \ $(FIGURES)/lte-epc-e2e-data-protocol-stack.eps \ + $(FIGURES)/MCS_2_test.eps \ + $(FIGURES)/MCS_12_test.eps \ + $(FIGURES)/MCS_14_test.eps \ + $(FIGURES)/lena-dual-stripe.eps \ $(FIGURES)/lte-mcs-index.eps \ $(FIGURES)/lenaThrTestCase1.eps \ $(FIGURES)/lenaThrTestCase2.eps \ diff --git a/doc/models/source/index.rst b/doc/models/source/index.rst index 9312ad8fa..62bedcdc1 100644 --- a/doc/models/source/index.rst +++ b/doc/models/source/index.rst @@ -18,6 +18,7 @@ This document is written in `reStructuredText + */ + + +#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', ] diff --git a/src/buildings/helper/building-allocator.cc b/src/buildings/helper/building-allocator.cc index 552e2bb85..fe4ed81ac 100644 --- a/src/buildings/helper/building-allocator.cc +++ b/src/buildings/helper/building-allocator.cc @@ -190,7 +190,9 @@ GridBuildingAllocator::Create (uint32_t n) const } double bxmax = bxmin + m_lengthX; double bymax = bymin + m_lengthY; - BoxValue boxValue (Box (bxmin, bxmax, bymin, bymax, 0, m_height)); + Box box (bxmin, bxmax, bymin, bymax, 0, m_height); + NS_LOG_LOGIC ("new building : " << box); + BoxValue boxValue (box); m_buildingFactory.Set ("Boundaries", boxValue); Ptr b = m_buildingFactory.Create (); //b->SetAttribute ("Boundaries", boxValue); diff --git a/src/buildings/helper/building-position-allocator.cc b/src/buildings/helper/building-position-allocator.cc index e958e40b1..d224f6e87 100644 --- a/src/buildings/helper/building-position-allocator.cc +++ b/src/buildings/helper/building-position-allocator.cc @@ -18,6 +18,7 @@ * Author: Nicola Baldo */ #include "building-position-allocator.h" +#include "ns3/buildings-mobility-model.h" #include "ns3/random-variable.h" #include "ns3/double.h" #include "ns3/uinteger.h" @@ -177,4 +178,77 @@ RandomRoomPositionAllocator::GetNext () const + + +NS_OBJECT_ENSURE_REGISTERED (SameRoomPositionAllocator); + +SameRoomPositionAllocator::SameRoomPositionAllocator () +{ + NS_FATAL_ERROR (" Constructor \"SameRoomPositionAllocator ()\" should not be used"); +} + + +SameRoomPositionAllocator::SameRoomPositionAllocator (NodeContainer c) + : m_nodes (c), + m_nodeIt (c.Begin ()) +{ +} + +TypeId +SameRoomPositionAllocator::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::SameRoomPositionAllocator") + .SetParent () + .SetGroupName ("Mobility") + .AddConstructor (); + return tid; +} + +Vector +SameRoomPositionAllocator::GetNext () const +{ + NS_LOG_FUNCTION (this); + UniformVariable rand; + if (m_nodeIt == m_nodes.End ()) + { + m_nodeIt = m_nodes.Begin (); + } + + NS_ASSERT_MSG (m_nodeIt != m_nodes.End (), "no node in container"); + + Ptr bmm = (*m_nodeIt)->GetObject (); + uint32_t roomx = bmm->GetRoomNumberX (); + uint32_t roomy = bmm->GetRoomNumberY (); + uint32_t floor = bmm->GetFloorNumber (); + NS_LOG_LOGIC ("considering room (" << roomx << ", " << roomy << ", " << floor << ")"); + + Ptr b = bmm->GetBuilding (); + Ptr pa = CreateObject (); + UniformVariable v; + BoxValue bv; + b->GetAttribute ("Boundaries", bv); + Box box = bv.Get (); + double rdx = (box.xMax - box.xMin) / b->GetNRoomsX (); + double rdy = (box.yMax - box.yMin) / b->GetNRoomsY (); + double rdz = (box.zMax - box.zMin) / b->GetNFloors (); + double x1 = box.xMin + rdx * roomx; + double x2 = box.xMin + rdx * (roomx + 1); + double y1 = box.yMin + rdy * roomy; + double y2 = box.yMin + rdy * (roomy + 1); + double z1 = box.zMin + rdz * floor; + double z2 = box.zMin + rdz * (floor + 1); + NS_LOG_LOGIC ("randomly allocating position in " + << " (" << x1 << "," << x2 << ") " + << "x (" << y1 << "," << y2 << ") " + << "x (" << z1 << "," << z2 << ") "); + + double x = v.GetValue (x1, x2); + double y = v.GetValue (y1, y2); + double z = v.GetValue (z1, z2); + + return Vector (x, y, z); +} + + + } // namespace ns3 diff --git a/src/buildings/helper/building-position-allocator.h b/src/buildings/helper/building-position-allocator.h index 433e7d58d..3690b2f0b 100644 --- a/src/buildings/helper/building-position-allocator.h +++ b/src/buildings/helper/building-position-allocator.h @@ -22,6 +22,7 @@ #include #include +#include namespace ns3 { @@ -82,6 +83,29 @@ private: }; +/** + * Walks a given NodeContainer sequentially, and for each node allocate a new + * position randomly in the same room of that node + * + */ +class SameRoomPositionAllocator : public PositionAllocator +{ +public: + SameRoomPositionAllocator (); + SameRoomPositionAllocator (NodeContainer c); + + // inherited from Object + static TypeId GetTypeId (void); + + // inherited from PositionAllocator + virtual Vector GetNext (void) const; + +private: + + NodeContainer m_nodes; + mutable NodeContainer::Iterator m_nodeIt; +}; + } // namespace ns3 diff --git a/src/lte/doc/Makefile b/src/lte/doc/Makefile index 033f8f224..ba9cd9c9e 100644 --- a/src/lte/doc/Makefile +++ b/src/lte/doc/Makefile @@ -25,10 +25,7 @@ IMAGES_EPS = \ $(FIGURES)/MCS_2_test.eps \ $(FIGURES)/MCS_12_test.eps \ $(FIGURES)/MCS_14_test.eps \ - $(FIGURES)/lena-dual-stripe.eps - -# specify figures for build process (figures for which both a .pdf and a .png files are provided) -GRAPHS_EPS = \ + $(FIGURES)/lena-dual-stripe.eps \ $(FIGURES)/lte-mcs-index.eps \ $(FIGURES)/lenaThrTestCase1.eps \ $(FIGURES)/lenaThrTestCase2.eps \ @@ -118,10 +115,6 @@ IMAGES = $(IMAGES_EPS) $(IMAGES_PNG) $(IMAGES_PDF) $(IMAGES_OTHER) %.pdf : %.seqdiag; $(SEQDIAG) -Tpdf -o $@ $< ; if test x$($@_width) != x; then TMPFILE=`mktemp`; ./rescale-pdf.sh $($@_width) $@ $${TMPFILE} && mv $${TMPFILE} $@; fi %.pdf : %.eps; $(EPSTOPDF) $< -o=$@; if test x$($@_width) != x; then TMPFILE=`mktemp`; ./rescale-pdf.sh $($@_width) $@ $${TMPFILE} && mv $${TMPFILE} $@; fi -GRAPHS_PNG = ${GRAPHS_EPS:.eps=.png} -GRAPHS_PDF = ${GRAPHS_EPS:.eps=.pdf} - -GRAPHS = $(GRAPHS_EPS) $(GRAPHS_PNG) $(GRAPHS_PDF) %.png : %.eps; $(CONVERT) $< $@ %.pdf : %.eps; $(EPSTOPDF) $< -o=$@; if test x$($@_width) != x; then TMPFILE=`mktemp`; ./rescale-pdf.sh $($@_width) $@ $${TMPFILE} && mv $${TMPFILE} $@; fi @@ -162,15 +155,13 @@ clean: -rm -rf $(BUILDDIR)/* -rm -f $(IMAGES_PNG) -rm -f $(IMAGES_PDF) - -rm -f $(GRAPHS_PNG) - -rm -f $(GRAPHS_PDF) frag: pickle @if test ! -d $(BUILDDIR)/frag; then mkdir $(BUILDDIR)/frag; fi pushd $(BUILDDIR)/frag && ../../pickle-to-xml.py ../pickle/index.fpickle > navigation.xml && popd cp -r $(BUILDDIR)/pickle/_images $(BUILDDIR)/frag -html: $(IMAGES) ${GRAPHS} +html: $(IMAGES) $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -224,14 +215,14 @@ epub: $(IMAGES) @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." -latex: $(IMAGES) ${GRAPHS} +latex: $(IMAGES) $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." -latexpdf: $(IMAGES) ${GRAPHS} +latexpdf: $(IMAGES) $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf diff --git a/src/lte/doc/source/lte-design.rst b/src/lte/doc/source/lte-design.rst index 9c95f1547..0e336ed4d 100644 --- a/src/lte/doc/source/lte-design.rst +++ b/src/lte/doc/source/lte-design.rst @@ -411,9 +411,9 @@ process in order to reach its destination UE. ------------------------------ -Description of the components ------------------------------ +----------------------------------------- +Detailed description of protocol elements +----------------------------------------- @@ -602,7 +602,7 @@ on resource block :math:`k` at subframe :math:`t` is defined as R_{i}(k,t) = \frac{S\left( M_{i,k}(t), 1\right)}{\tau} where :math:`\tau` is the TTI duration. -At the start of each subframe :math:`t`, all the RBs are assigned to a certain user. +At the start of each subframe :math:`t`, each RB is assigned to a certain user. In detail, the index :math:`\widehat{i}_{k}(t)` to which RB :math:`k` is assigned at time :math:`t` is determined as diff --git a/src/lte/doc/source/lte-rlc.rst b/src/lte/doc/source/lte-rlc.rst deleted file mode 100644 index b3321051e..000000000 --- a/src/lte/doc/source/lte-rlc.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. only:: html or latex - -###################################### -LTE Simulator RLC Layer Documentation -###################################### - -.. toctree:: - :maxdepth: 5 - - lte-rlc-design - lte-references - - - diff --git a/src/lte/examples/lena-dual-stripe.cc b/src/lte/examples/lena-dual-stripe.cc index 7bf025e76..fa277f252 100644 --- a/src/lte/examples/lena-dual-stripe.cc +++ b/src/lte/examples/lena-dual-stripe.cc @@ -43,19 +43,152 @@ using namespace ns3; NS_LOG_COMPONENT_DEFINE ("LenaDualStripe"); + +bool AreOverlapping (Box a, Box b) +{ + return !((a.xMin > b.xMax) || (b.xMin > a.xMax) || (a.yMin > b.yMax) || (b.yMin > a.yMax)); +} + +class FemtocellBlockAllocator +{ +public: + FemtocellBlockAllocator (Box area, uint32_t nApartmentsX, uint32_t nFloors); + void Create (uint32_t n); + void Create (); + +private: + bool OverlapsWithAnyPrevious (Box); + Box m_area; + uint32_t m_nApartmentsX; + uint32_t m_nFloors; + std::list m_previousBlocks; + double m_xSize; + double m_ySize; + UniformVariable m_xMinVar; + UniformVariable m_yMinVar; + +}; + +FemtocellBlockAllocator::FemtocellBlockAllocator (Box area, uint32_t nApartmentsX, uint32_t nFloors) + : m_area (area), + m_nApartmentsX (nApartmentsX), + m_nFloors (nFloors), + m_xSize (nApartmentsX*10 + 20), + m_ySize (70), + m_xMinVar (area.xMin, area.xMax - m_xSize), + m_yMinVar (area.yMin, area.yMax - m_ySize) +{ + +} + +void +FemtocellBlockAllocator::Create (uint32_t n) +{ + for (uint32_t i = 0; i < n; ++i) + { + Create (); + } +} + +void +FemtocellBlockAllocator::Create () +{ + Box box; + uint32_t attempt = 0; + do + { + NS_ASSERT_MSG (attempt < 100, "Too many failed attemtps to position apartment block. Too many blocks? Too small area?"); + box.xMin = m_xMinVar.GetValue (); + box.xMax = box.xMin + m_xSize; + box.yMin = m_yMinVar.GetValue (); + box.yMax = box.yMin + m_ySize; + ++attempt; + } + while (OverlapsWithAnyPrevious (box)); + + NS_LOG_LOGIC ("allocated non overlapping block " << box); + m_previousBlocks.push_back (box); + Ptr gridBuildingAllocator; + gridBuildingAllocator = CreateObject (); + gridBuildingAllocator->SetAttribute ("GridWidth", UintegerValue (1)); + gridBuildingAllocator->SetAttribute ("LengthX", DoubleValue (10*m_nApartmentsX)); + gridBuildingAllocator->SetAttribute ("LengthY", DoubleValue (10*2)); + gridBuildingAllocator->SetAttribute ("DeltaX", DoubleValue (10)); + gridBuildingAllocator->SetAttribute ("DeltaY", DoubleValue (10)); + gridBuildingAllocator->SetAttribute ("Height", DoubleValue (3*m_nFloors)); + gridBuildingAllocator->SetBuildingAttribute ("NRoomsX", UintegerValue (m_nApartmentsX)); + gridBuildingAllocator->SetBuildingAttribute ("NRoomsY", UintegerValue (2)); + gridBuildingAllocator->SetBuildingAttribute ("NFloors", UintegerValue (m_nFloors)); + gridBuildingAllocator->SetAttribute ("MinX", DoubleValue (box.xMin + 10)); + gridBuildingAllocator->SetAttribute ("MinY", DoubleValue (box.yMin + 10)); + gridBuildingAllocator->Create (2); +} + +bool +FemtocellBlockAllocator::OverlapsWithAnyPrevious (Box box) +{ + for (std::list::iterator it = m_previousBlocks.begin (); it != m_previousBlocks.end (); ++it) + { + if (AreOverlapping (*it, box)) + { + return true; + } + } + return false; +} + int main (int argc, char *argv[]) { // scenario parameters - uint32_t nBlocks = 2; - uint32_t nApartamentsX = 10; - uint32_t nApartamentsY = 2; + uint32_t nBlocks = 10; + uint32_t nApartmentsX = 10; uint32_t nFloors = 1; - uint32_t heightPerFloor = 3; - double deploymentRatio = 0.4; - double ueHenbRatio = 10; - + uint32_t nMacroEnbSites = 3; + uint32_t nMacroEnbSitesX = 1; + double interSiteDistance = 500; + double areaMarginFactor = 0.5; + double macroUeDensity = 0.0001; + double homeEnbDeploymentRatio = 0.2; + double homeEnbActivationRatio = 0.5; + double homeUesHomeEnbRatio = 1; + double macroEnbTxPowerDbm = 46.0; + double homeEnbTxPowerDbm = 20.0; + uint16_t macroEnbDlEarfcn = 100; + uint16_t homeEnbDlEarfcn = 100; + uint8_t macroEnbBandwidth = 25; + uint8_t homeEnbBandwidth = 25; + double simTime = 0.01; + bool generateRem = false; + CommandLine cmd; + cmd.AddValue ("nBlocks", "Number of femtocell blocks", nBlocks); + cmd.AddValue ("nApartmentsX", "Number of apartments along the X axis in a femtocell block", nApartmentsX); + cmd.AddValue ("nFloors", "Number of floors", nFloors); + cmd.AddValue ("nMacroEnbSites", "How many macro sites there are", nMacroEnbSites); + cmd.AddValue ("nMacroEnbSitesX", + "(minimum) number of sites along the X-axis of the hex grid", nMacroEnbSitesX); + cmd.AddValue ("interSiteDistance", "min distance between two nearby macro cell sites", interSiteDistance); + cmd.AddValue ("areaMarginFactor", "how much the UE area extends outside the macrocell grid, " + "expressed as fraction of the interSiteDistance", areaMarginFactor); + cmd.AddValue ("macroUeDensity", "How many macrocell UEs there are per square meter", macroUeDensity); + cmd.AddValue ("homeEnbDeploymentRatio", + "The HeNB deployment ratio as per 3GPP R4-092042", homeEnbDeploymentRatio); + cmd.AddValue ("homeEnbActivationRatio", + "The HeNB activation ratio as per 3GPP R4-092042", homeEnbActivationRatio); + cmd.AddValue ("homeUesHomeEnbRatio", + "How many (on average) home UEs per HeNB there are in the simulation", + homeUesHomeEnbRatio); + cmd.AddValue ("macroEnbTxPowerDbm", "TX power [dBm] used by macro eNBs", macroEnbTxPowerDbm); + cmd.AddValue ("homeEnbTxPowerDbm", "TX power [dBm] used by HeNBs", homeEnbTxPowerDbm); + cmd.AddValue ("macroEnbDlEarfcn", "DL EARFCN used by macro eNBs", macroEnbDlEarfcn); + cmd.AddValue ("homeEnbDlEarfcn", "DL EARFCN used by HeNBs", homeEnbDlEarfcn); + cmd.AddValue ("macroEnbBandwidth", "bandwdith [num RBs] used by macro eNBs", macroEnbBandwidth); + cmd.AddValue ("homeEnbBandwidth", "bandwdith [num RBs] used by HeNBs", homeEnbBandwidth); + cmd.AddValue ("simTime", "Total duration of the simulation [s]", simTime); + cmd.AddValue ("generateRem", "if true, will generate a REM and then abort the simulation;" + "if false, will run the simulation normally (without generating any REM)", generateRem); + cmd.Parse (argc, argv); ConfigStore inputConfig; @@ -63,122 +196,142 @@ main (int argc, char *argv[]) cmd.Parse (argc, argv); - + uint32_t currentSite = nMacroEnbSites -1; + uint32_t biRowIndex = (currentSite / (nMacroEnbSitesX + nMacroEnbSitesX + 1)); + uint32_t biRowRemainder = currentSite % (nMacroEnbSitesX + nMacroEnbSitesX + 1); + uint32_t rowIndex = biRowIndex*2 + 1; + if (biRowRemainder >= nMacroEnbSitesX) + { + ++rowIndex; + } + uint32_t nMacroEnbSitesY = rowIndex; + NS_LOG_LOGIC ("nMacroEnbSitesY = " << nMacroEnbSitesY); - Ptr gridBuildingAllocator = CreateObject (); - gridBuildingAllocator->SetAttribute ("GridWidth", UintegerValue (1)); - gridBuildingAllocator->SetAttribute ("MinX", DoubleValue (0)); - gridBuildingAllocator->SetAttribute ("MinY", DoubleValue (0)); - gridBuildingAllocator->SetAttribute ("LengthX", DoubleValue (10*nApartamentsX)); - gridBuildingAllocator->SetAttribute ("LengthY", DoubleValue (10*nApartamentsY)); - gridBuildingAllocator->SetAttribute ("DeltaX", DoubleValue (10)); - gridBuildingAllocator->SetAttribute ("DeltaY", DoubleValue (10)); - gridBuildingAllocator->SetAttribute ("Height", DoubleValue (heightPerFloor*nFloors)); - gridBuildingAllocator->SetBuildingAttribute ("NRoomsX", UintegerValue (nApartamentsX)); - gridBuildingAllocator->SetBuildingAttribute ("NRoomsY", UintegerValue (nApartamentsY)); - gridBuildingAllocator->SetBuildingAttribute ("NFloors", UintegerValue (nFloors)); - gridBuildingAllocator->SetBuildingAttribute ("ExternalWallsType", EnumValue (Building::StoneBlocks)); - gridBuildingAllocator->Create (nBlocks); - - uint32_t nHenbs = round (nApartamentsX * nApartamentsY * nBlocks * nFloors * deploymentRatio); - NS_LOG_LOGIC ("nHenbs = " << nHenbs); - uint32_t nUes = round (nHenbs*ueHenbRatio); - NS_LOG_LOGIC ("nUes = " << nUes); + Box macroUeBox (-areaMarginFactor*interSiteDistance, + (nMacroEnbSitesX + areaMarginFactor)*interSiteDistance, + -areaMarginFactor*interSiteDistance, + (nMacroEnbSitesY -1)*interSiteDistance*sqrt(0.75) + areaMarginFactor*interSiteDistance, + 1.0, 2.0); - NodeContainer henbs; - henbs.Create (nHenbs); + FemtocellBlockAllocator blockAllocator (macroUeBox, nApartmentsX, nFloors); + blockAllocator.Create (nBlocks); + + + uint32_t nHomeEnbs = round (4 * nApartmentsX * nBlocks * nFloors * homeEnbDeploymentRatio * homeEnbActivationRatio); + NS_LOG_LOGIC ("nHomeEnbs = " << nHomeEnbs); + uint32_t nHomeUes = round (nHomeEnbs * homeUesHomeEnbRatio); + NS_LOG_LOGIC ("nHomeUes = " << nHomeUes); + double macroUeAreaSize = (macroUeBox.xMax - macroUeBox.xMin) * (macroUeBox.yMax - macroUeBox.yMin); + uint32_t nMacroUes = round (macroUeAreaSize * macroUeDensity) ; + NS_LOG_LOGIC ("nMacroUes = " << nMacroUes); + + NodeContainer homeEnbs; + homeEnbs.Create (nHomeEnbs); NodeContainer macroEnbs; - macroEnbs.Create (3); - NodeContainer ues; - ues.Create (nUes); + macroEnbs.Create (3 * nMacroEnbSites); + NodeContainer homeUes; + homeUes.Create (nHomeUes); + NodeContainer macroUes; + macroUes.Create (nMacroUes); MobilityHelper mobility; mobility.SetMobilityModel ("ns3::BuildingsMobilityModel"); - mobility.EnableAsciiAll (std::cout); - // HeNBs placed indoor - Ptr positionAlloc = CreateObject (); - mobility.SetPositionAllocator (positionAlloc); - mobility.Install (henbs); - - // Macro eNB placed at fixed coordinates - Ptr listPositionAlloc = CreateObject (); - listPositionAlloc->Add (Vector (-50, 0, 30)); - listPositionAlloc->Add (Vector (-50.01, 0.01, 30)); - listPositionAlloc->Add (Vector (-50.01, -0.01, 30)); - mobility.SetPositionAllocator (listPositionAlloc); - mobility.Install (macroEnbs); - - // UEs randomly located in the whole simulation area - double xmin = -100; - double xmax = nApartamentsX*10+10; - double ymin = -50; - double ymax = (nApartamentsY*10+10)*nBlocks; - double zmin = 0; - double zmax = heightPerFloor*nFloors; - NS_LOG_LOGIC ("randomly allocating users in " - << " (" << xmin << "," << xmax << ") " - << "x (" << ymin << "," << ymax << ") " - << "x (" << zmin << "," << zmax << ") "); - positionAlloc = CreateObject (); - positionAlloc->SetAttribute ("X", RandomVariableValue (UniformVariable (xmin, xmax))); - positionAlloc->SetAttribute ("Y", RandomVariableValue (UniformVariable (ymin, ymax))); - positionAlloc->SetAttribute ("Z", RandomVariableValue (UniformVariable (zmin, zmax))); - mobility.SetPositionAllocator (positionAlloc); - mobility.Install (ues); - - Ptr lteHelper = CreateObject (); - // //lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisPropagationLossModel")); lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::HybridBuildingsPropagationLossModel")); lteHelper->SetPathlossModelAttribute ("ShadowSigmaExtWalls", DoubleValue (0)); lteHelper->SetPathlossModelAttribute ("ShadowSigmaOutdoor", DoubleValue (1)); lteHelper->SetPathlossModelAttribute ("ShadowSigmaIndoor", DoubleValue (1.5)); + // use always LOS model + lteHelper->SetPathlossModelAttribute ("Los2NlosThr", DoubleValue (1e6)); + lteHelper->SetSpectrumChannelType ("ns3::MultiModelSpectrumChannel"); + + + + // Macro eNBs in 3-sector hex grid + + mobility.Install (macroEnbs); + Ptr lteHexGridEnbTopologyHelper = CreateObject (); + lteHexGridEnbTopologyHelper->SetLteHelper (lteHelper); + lteHexGridEnbTopologyHelper->SetAttribute ("InterSiteDistance", DoubleValue (interSiteDistance)); + lteHexGridEnbTopologyHelper->SetAttribute ("MinX", DoubleValue (interSiteDistance/2)); + lteHexGridEnbTopologyHelper->SetAttribute ("GridWidth", UintegerValue (nMacroEnbSitesX)); + Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (macroEnbTxPowerDbm)); + lteHelper->SetEnbAntennaModelType ("ns3::ParabolicAntennaModel"); + lteHelper->SetEnbAntennaModelAttribute ("Beamwidth", DoubleValue (70)); + lteHelper->SetEnbAntennaModelAttribute ("MaxAttenuation", DoubleValue (20.0)); + lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (macroEnbDlEarfcn)); + lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (macroEnbDlEarfcn + 18000)); + lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (macroEnbBandwidth)); + lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (macroEnbBandwidth)); + NetDeviceContainer macroEnbDevs = lteHexGridEnbTopologyHelper->SetPositionAndInstallEnbDevice (macroEnbs); - // Create Devices and install them in the Nodes (eNB and UE) - NetDeviceContainer enbDevs; - NetDeviceContainer ueDevs; + // HomeEnbs randomly indoor + + Ptr positionAlloc = CreateObject (); + mobility.SetPositionAllocator (positionAlloc); + mobility.Install (homeEnbs); + Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (homeEnbTxPowerDbm)); + lteHelper->SetEnbAntennaModelType ("ns3::IsotropicAntennaModel"); + lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (homeEnbDlEarfcn)); + lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (homeEnbDlEarfcn + 18000)); + lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (homeEnbBandwidth)); + lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (homeEnbBandwidth)); + NetDeviceContainer homeEnbDevs = lteHelper->InstallEnbDevice (homeEnbs); + - // power setting in dBm for HeNBs - Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (10.0)); - enbDevs.Add (lteHelper->InstallEnbDevice (henbs)); + // macro Ues + NS_LOG_LOGIC ("randomly allocating macro UEs in " << macroUeBox); + positionAlloc = CreateObject (); + positionAlloc->SetAttribute ("X", RandomVariableValue (UniformVariable (macroUeBox.xMin, macroUeBox.xMax))); + positionAlloc->SetAttribute ("Y", RandomVariableValue (UniformVariable (macroUeBox.yMin, macroUeBox.yMax))); + positionAlloc->SetAttribute ("Z", RandomVariableValue (UniformVariable (macroUeBox.zMin, macroUeBox.zMax))); + mobility.SetPositionAllocator (positionAlloc); + mobility.Install (macroUes); + NetDeviceContainer macroUeDevs = lteHelper->InstallUeDevice (macroUes); + lteHelper->AttachToClosestEnb (macroUeDevs, macroEnbDevs); - // power setting in dBm for macro eNB - Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (30.0)); - lteHelper->SetEnbAntennaModelType ("ns3::CosineAntennaModel"); - lteHelper->SetEnbAntennaModelAttribute ("Beamwidth", DoubleValue (65)); - lteHelper->SetEnbAntennaModelAttribute ("MaxGain", DoubleValue (0.0)); - lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (0)); - enbDevs.Add (lteHelper->InstallEnbDevice (macroEnbs.Get (0))); - lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (+120)); - enbDevs.Add (lteHelper->InstallEnbDevice (macroEnbs.Get (1))); - lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (-120)); - enbDevs.Add (lteHelper->InstallEnbDevice (macroEnbs.Get (2))); + // home UEs located in the same apartment in which there are the Home eNBs + positionAlloc = CreateObject (homeEnbs); + mobility.Install (homeUes); + NetDeviceContainer homeUeDevs = lteHelper->InstallUeDevice (homeUes); + lteHelper->AttachToClosestEnb (homeUeDevs, homeEnbDevs); - ueDevs = lteHelper->InstallUeDevice (ues); - lteHelper->AttachToClosestEnb (ueDevs, enbDevs); + + + // activate bearer for all UEs enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE; EpsBearer bearer (q); - lteHelper->ActivateEpsBearer (ueDevs, bearer, EpcTft::Default ()); + lteHelper->ActivateEpsBearer (homeUeDevs, bearer, EpcTft::Default ()); + lteHelper->ActivateEpsBearer (macroUeDevs, bearer, EpcTft::Default ()); + BuildingsHelper::MakeMobilityModelConsistent (); - // by default, simulation will anyway stop right after the REM has been generated - Simulator::Stop (Seconds (0.0069)); - Ptr remHelper = CreateObject (); - remHelper->SetAttribute ("ChannelPath", StringValue ("/ChannelList/0")); - remHelper->SetAttribute ("OutputFile", StringValue ("lena-dual-stripe.rem")); - remHelper->SetAttribute ("XMin", DoubleValue (-70)); - remHelper->SetAttribute ("XMax", DoubleValue (xmax)); - remHelper->SetAttribute ("YMin", DoubleValue (-10)); - remHelper->SetAttribute ("YMax", DoubleValue (ymax)); - remHelper->SetAttribute ("Z", DoubleValue (1.5)); - remHelper->Install (); + + Ptr remHelper; + if (generateRem) + { + remHelper = CreateObject (); + remHelper->SetAttribute ("ChannelPath", StringValue ("/ChannelList/0")); + remHelper->SetAttribute ("OutputFile", StringValue ("lena-dual-stripe.rem")); + remHelper->SetAttribute ("XMin", DoubleValue (macroUeBox.xMin)); + remHelper->SetAttribute ("XMax", DoubleValue (macroUeBox.xMax)); + remHelper->SetAttribute ("YMin", DoubleValue (macroUeBox.yMin)); + remHelper->SetAttribute ("YMax", DoubleValue (macroUeBox.yMax)); + remHelper->SetAttribute ("Z", DoubleValue (1.5)); + remHelper->Install (); + // simulation will stop right after the REM has been generated + } + else + { + Simulator::Stop (Seconds (simTime)); + } Simulator::Run (); diff --git a/src/lte/examples/lena-rem-sector-antenna.cc b/src/lte/examples/lena-rem-sector-antenna.cc index e914dcca0..d2ca509db 100644 --- a/src/lte/examples/lena-rem-sector-antenna.cc +++ b/src/lte/examples/lena-rem-sector-antenna.cc @@ -29,7 +29,7 @@ #include #include #include -#include "ns3/gtk-config-store.h" +//#include "ns3/gtk-config-store.h" using namespace ns3; using std::vector; diff --git a/src/lte/examples/lena-rem.cc b/src/lte/examples/lena-rem.cc index 2acac3d1b..a4d7e6c74 100644 --- a/src/lte/examples/lena-rem.cc +++ b/src/lte/examples/lena-rem.cc @@ -108,8 +108,6 @@ int main (int argc, char *argv[]) BuildingsHelper::MakeMobilityModelConsistent (); - // by default, simulation will anyway stop right after the REM has been generated - Simulator::Stop (Seconds (0.0069)); Simulator::Run (); diff --git a/src/lte/helper/lte-helper.cc b/src/lte/helper/lte-helper.cc index f1c22300e..aa3b48602 100644 --- a/src/lte/helper/lte-helper.cc +++ b/src/lte/helper/lte-helper.cc @@ -62,14 +62,15 @@ LteHelper::LteHelper (void) m_enbNetDeviceFactory.SetTypeId (LteEnbNetDevice::GetTypeId ()); m_enbAntennaModelFactory.SetTypeId (IsotropicAntennaModel::GetTypeId ()); m_ueAntennaModelFactory.SetTypeId (IsotropicAntennaModel::GetTypeId ()); + m_channelFactory.SetTypeId (SingleModelSpectrumChannel::GetTypeId ()); } void LteHelper::DoStart (void) { NS_LOG_FUNCTION (this); - m_downlinkChannel = CreateObject (); - m_uplinkChannel = CreateObject (); + m_downlinkChannel = m_channelFactory.Create (); + m_uplinkChannel = m_channelFactory.Create (); m_downlinkPathlossModel = m_dlPathlossModelFactory.Create (); Ptr dlSplm = m_downlinkPathlossModel->GetObject (); @@ -101,7 +102,6 @@ LteHelper::DoStart (void) m_uplinkChannel->AddPropagationLossModel (ulPlm); } - //if (m_fadingModelFactory.GetTypeId ().GetName ().compare ( "ns3::TraceFadingLossModel") == 0) if (m_fadingModelType.compare ( "ns3::TraceFadingLossModel") == 0) { m_fadingModule = m_fadingModelFactory.Create (); @@ -265,6 +265,19 @@ LteHelper::SetFadingModelAttribute (std::string n, const AttributeValue &v) m_fadingModelFactory.Set (n, v); } +void +LteHelper::SetSpectrumChannelType (std::string type) +{ + NS_LOG_FUNCTION (this << type); + m_channelFactory.SetTypeId (type); +} + +void +LteHelper::SetSpectrumChannelAttribute (std::string n, const AttributeValue &v) +{ + m_channelFactory.Set (n, v); +} + NetDeviceContainer LteHelper::InstallEnbDevice (NodeContainer c) @@ -317,7 +330,6 @@ LteHelper::InstallSingleEnbDevice (Ptr n) NS_ASSERT_MSG (mm, "MobilityModel needs to be set on node before calling LteHelper::InstallUeDevice ()"); dlPhy->SetMobility (mm); ulPhy->SetMobility (mm); - m_uplinkChannel->AddRx (ulPhy); Ptr antenna = (m_enbAntennaModelFactory.Create ())->GetObject (); NS_ASSERT_MSG (antenna, "error in creating the AntennaModel object"); @@ -378,6 +390,8 @@ LteHelper::InstallSingleEnbDevice (Ptr n) dev->Start (); + m_uplinkChannel->AddRx (ulPhy); + if (m_epcHelper != 0) { NS_LOG_INFO ("adding this eNB to the EPC"); @@ -410,7 +424,6 @@ LteHelper::InstallSingleUeDevice (Ptr n) dlPhy->SetMobility (mm); ulPhy->SetMobility (mm); - m_downlinkChannel->AddRx (dlPhy); Ptr antenna = (m_ueAntennaModelFactory.Create ())->GetObject (); NS_ASSERT_MSG (antenna, "error in creating the AntennaModel object"); @@ -470,7 +483,6 @@ LteHelper::Attach (Ptr ueDevice, Ptr enbDevice) Ptr uePhy = ueDevice->GetObject ()->GetPhy (); enbPhy->AddUePhy (rnti, uePhy); - //if (m_fadingModelFactory.GetTypeId ().GetName ().compare ( "ns3::TraceFadingLossModel") == 0) if (m_fadingModelType.compare ( "ns3::TraceFadingLossModel") == 0) { Ptr mm_enb_dl = enbPhy->GetDownlinkSpectrumPhy ()->GetMobility ()->GetObject (); @@ -491,6 +503,8 @@ LteHelper::Attach (Ptr ueDevice, Ptr enbDevice) enbDevice->GetObject ()->GetUlEarfcn ()); ueDevice->Start (); + + m_downlinkChannel->AddRx (uePhy->GetDownlinkSpectrumPhy ()); } void @@ -614,32 +628,6 @@ LteHelper::EnableLogComponents (void) LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL); std::string propModelStr = m_dlPathlossModelFactory.GetTypeId ().GetName ().erase (0,5).c_str (); -/* - const char* propModel = m_dlPathlossModelFactory.GetTypeId ().GetName ().erase (0,5).c_str (); - if (propModelStr.compare ("RandomPropagationLossModel") || - propModelStr.compare ("FriisPropagationLossModel")|| - propModelStr.compare ("TwoRayGroundPropagationLossModel")|| - propModelStr.compare ("LogDistancePropagationLossModel")|| - propModelStr.compare ("ThreeLogDistancePropagationLossModel")|| - propModelStr.compare ("NakagamiPropagationLossModel")|| - propModelStr.compare ("FixedRssLossModel")|| - propModelStr.compare ("MatrixPropagationLossModel")|| - propModelStr.compare ("RangePropagationLossModel")) - { - LogComponentEnable ("PropagationLossModel", LOG_LEVEL_ALL); - } - else - { - LogComponentEnable (propModel, LOG_LEVEL_ALL); - } - - if (m_fadingModelType.compare ("ns3::TraceFadingLossModel") == 0) - { - const char* fadingModel = m_fadingModelType.erase (0,5).c_str (); - LogComponentEnable (fadingModel, LOG_LEVEL_ALL); - } - LogComponentEnable ("SingleModelSpectrumChannel", LOG_LEVEL_ALL); -*/ LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL); LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL); LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL); diff --git a/src/lte/helper/lte-helper.h b/src/lte/helper/lte-helper.h index 4f2db75ac..bb9a51612 100644 --- a/src/lte/helper/lte-helper.h +++ b/src/lte/helper/lte-helper.h @@ -138,6 +138,19 @@ public: */ void SetUeAntennaModelAttribute (std::string n, const AttributeValue &v); + /** + * + * \param type the type of SpectrumChannel to be used for the UEs + */ + void SetSpectrumChannelType (std::string type); + + /** + * set an attribute for the SpectrumChannel to be used for the UEs + * + * \param n the name of the attribute + * \param v the value of the attribute + */ + void SetSpectrumChannelAttribute (std::string n, const AttributeValue &v); /** * create a set of eNB devices * @@ -322,6 +335,8 @@ private: ObjectFactory m_dlPathlossModelFactory; ObjectFactory m_ulPathlossModelFactory; + ObjectFactory m_channelFactory; + std::string m_fadingModelType; ObjectFactory m_fadingModelFactory; diff --git a/src/lte/helper/lte-hex-grid-enb-topology-helper.cc b/src/lte/helper/lte-hex-grid-enb-topology-helper.cc new file mode 100644 index 000000000..6fdc354fe --- /dev/null +++ b/src/lte/helper/lte-hex-grid-enb-topology-helper.cc @@ -0,0 +1,171 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Nicola Baldo + */ + + +#include "lte-hex-grid-enb-topology-helper.h" +#include +#include +#include +#include +#include +#include + + +NS_LOG_COMPONENT_DEFINE ("LteHexGridEnbTopologyHelper"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (LteHexGridEnbTopologyHelper); + +LteHexGridEnbTopologyHelper::LteHexGridEnbTopologyHelper () +{ + NS_LOG_FUNCTION (this); +} + +LteHexGridEnbTopologyHelper::~LteHexGridEnbTopologyHelper (void) +{ + NS_LOG_FUNCTION (this); +} + +TypeId LteHexGridEnbTopologyHelper::GetTypeId (void) +{ + static TypeId + tid = + TypeId ("ns3::LteHexGridEnbTopologyHelper") + .SetParent () + .AddConstructor () + .AddAttribute ("InterSiteDistance", + "The distance [m] between nearby sites", + DoubleValue (500), + MakeDoubleAccessor (&LteHexGridEnbTopologyHelper::m_d), + MakeDoubleChecker ()) + .AddAttribute ("SectorOffset", + "The offset [m] in the position for the node of each sector with respect " + "to the center of the three-sector site", + DoubleValue (0.5), + MakeDoubleAccessor (&LteHexGridEnbTopologyHelper::m_offset), + MakeDoubleChecker ()) + .AddAttribute ("SiteHeight", + "The height [m] of each site", + DoubleValue (30), + MakeDoubleAccessor (&LteHexGridEnbTopologyHelper::m_siteHeight), + MakeDoubleChecker ()) + .AddAttribute ("MinX", "The x coordinate where the hex grid starts.", + DoubleValue (0.0), + MakeDoubleAccessor (&LteHexGridEnbTopologyHelper::m_xMin), + MakeDoubleChecker ()) + .AddAttribute ("MinY", "The y coordinate where the hex grid starts.", + DoubleValue (0.0), + MakeDoubleAccessor (&LteHexGridEnbTopologyHelper::m_yMin), + MakeDoubleChecker ()) + .AddAttribute ("GridWidth", "The number of sites in even rows (odd rows will have one additional site).", + UintegerValue (1), + MakeUintegerAccessor (&LteHexGridEnbTopologyHelper::m_gridWidth), + MakeUintegerChecker ()) + ; + return tid; +} + +void +LteHexGridEnbTopologyHelper::DoDispose () +{ + NS_LOG_FUNCTION (this); + Object::DoDispose (); +} + + +void +LteHexGridEnbTopologyHelper::SetLteHelper (Ptr h) +{ + NS_LOG_FUNCTION (this << h); + m_lteHelper = h; +} + +NetDeviceContainer +LteHexGridEnbTopologyHelper::SetPositionAndInstallEnbDevice (NodeContainer c) +{ + NS_LOG_FUNCTION (this); + NetDeviceContainer enbDevs; + const double xydfactor = sqrt (0.75); + double yd = xydfactor*m_d; + for (uint32_t n = 0; n < c.GetN (); ++n) + { + uint32_t currentSite = n / 3; + uint32_t biRowIndex = (currentSite / (m_gridWidth + m_gridWidth + 1)); + uint32_t biRowRemainder = currentSite % (m_gridWidth + m_gridWidth + 1); + uint32_t rowIndex = biRowIndex*2; + uint32_t colIndex = biRowRemainder; + if (biRowRemainder >= m_gridWidth) + { + ++rowIndex; + colIndex -= m_gridWidth; + } + NS_LOG_LOGIC ("node " << n << " site " << currentSite + << " rowIndex " << rowIndex + << " colIndex " << colIndex + << " biRowIndex " << biRowIndex + << " biRowRemainder " << biRowRemainder); + double y = m_yMin + yd * rowIndex; + double x; + double antennaOrientation; + if ((rowIndex % 2) == 0) + { + x = m_xMin + m_d * colIndex; + } + else // row is odd + { + x = m_xMin -(0.5*m_d) + m_d * colIndex; + } + + switch (n%3) + { + case 0: + antennaOrientation = 0; + x += m_offset; + break; + + case 1: + antennaOrientation = 120; + x -= m_offset/2.0; + y += m_offset*xydfactor; + break; + + case 2: + antennaOrientation = -120; + x -= m_offset/2.0; + y -= m_offset*xydfactor; + break; + + default: + break; + } + Ptr node = c.Get (n); + Ptr mm = node->GetObject (); + Vector pos (x, y, m_siteHeight); + NS_LOG_LOGIC ("node " << n << " at " << pos << " antennaOrientation " << antennaOrientation); + mm->SetPosition (Vector (x, y, m_siteHeight)); + m_lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (antennaOrientation)); + enbDevs.Add (m_lteHelper->InstallEnbDevice (node)); + } + return enbDevs; +} + +} // namespace ns3 + diff --git a/src/lte/helper/lte-hex-grid-enb-topology-helper.h b/src/lte/helper/lte-hex-grid-enb-topology-helper.h new file mode 100644 index 000000000..e41b33a57 --- /dev/null +++ b/src/lte/helper/lte-hex-grid-enb-topology-helper.h @@ -0,0 +1,87 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Nicola Baldo + */ + +#ifndef LTE_HEX_GRID_ENB_TOPOLOGY_HELPER_H +#define LTE_HEX_GRID_ENB_TOPOLOGY_HELPER_H + +#include + +namespace ns3 { + + + +/** + * This helper class allows to easily create a topology with eNBs + * grouped in three-sector sites layed out on an hexagonal grid. The + * layout is done row-wise. + * + */ +class LteHexGridEnbTopologyHelper : public Object +{ +public: + LteHexGridEnbTopologyHelper (void); + virtual ~LteHexGridEnbTopologyHelper (void); + + static TypeId GetTypeId (void); + virtual void DoDispose (void); + + + /** + * Set the LteHelper to be used to actually create the EnbNetDevices + * + * \note if no EpcHelper is ever set, then LteHexGridEnbTopologyHelper will default + * to creating an LTE-only simulation with no EPC, using LteRlcSm as + * the RLC model, and without supporting any IP networking. In other + * words, it will be a radio-level simulation involving only LTE PHY + * and MAC and the FF Scheduler, with a saturation traffic model for + * the RLC. + * + * \param h a pointer to the EpcHelper to be used + */ + void SetLteHelper (Ptr h); + + /** + * Position the nodes on a hex grid and install the corresponding + * EnbNetDevices with antenna boresight configured properly + * + * \param c the node container where the devices are to be installed + * + * \return the NetDeviceContainer with the newly created devices + */ + NetDeviceContainer SetPositionAndInstallEnbDevice (NodeContainer c); + +private: + + Ptr m_lteHelper; + double m_offset; + double m_d; + double m_xMin; + double m_yMin; + uint32_t m_gridWidth; + uint32_t m_siteHeight; + +}; + + +} // namespace ns3 + + + +#endif // LTE_HEX_GRID_ENB_TOPOLOGY_HELPER_H diff --git a/src/lte/helper/radio-environment-map-helper.cc b/src/lte/helper/radio-environment-map-helper.cc index a858f3fd6..dbaa63855 100644 --- a/src/lte/helper/radio-environment-map-helper.cc +++ b/src/lte/helper/radio-environment-map-helper.cc @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -101,7 +102,7 @@ RadioEnvironmentMapHelper::GetTypeId (void) .AddAttribute ("YRes", "The resolution (number of points) of the map along the y axis.", UintegerValue (100), MakeUintegerAccessor (&RadioEnvironmentMapHelper::m_yRes), - MakeUintegerChecker (2,std::numeric_limits::max ())) + MakeUintegerChecker (2,std::numeric_limits::max ())) .AddAttribute ("Z", "The value of the z coordinate for which the map is to be generated", DoubleValue (0.0), MakeDoubleAccessor (&RadioEnvironmentMapHelper::m_z), @@ -115,11 +116,53 @@ RadioEnvironmentMapHelper::GetTypeId (void) DoubleValue (1.4230e-10), MakeDoubleAccessor (&RadioEnvironmentMapHelper::m_noisePower), MakeDoubleChecker ()) + .AddAttribute ("MaxPointsPerIteration", "Maximum number of REM points to be calculated per iteration. Every point consumes approximately 5KB of memory.", + UintegerValue (20000), + MakeUintegerAccessor (&RadioEnvironmentMapHelper::m_maxPointsPerIteration), + MakeUintegerChecker (1,std::numeric_limits::max ())) + .AddAttribute ("Earfcn", + "E-UTRA Absolute Radio Frequency Channel Number (EARFCN) " + "as per 3GPP 36.101 Section 5.7.3. ", + UintegerValue (100), + MakeUintegerAccessor (&RadioEnvironmentMapHelper::m_earfcn), + MakeUintegerChecker ()) + .AddAttribute ("Bandwidth", + "Transmission Bandwidth Configuration (in number of RBs) over which the SINR will be calculated", + UintegerValue (25), + MakeUintegerAccessor (&RadioEnvironmentMapHelper::SetBandwidth, + &RadioEnvironmentMapHelper::GetBandwidth), + MakeUintegerChecker ()) ; return tid; } +uint8_t +RadioEnvironmentMapHelper::GetBandwidth () const +{ + return m_bandwidth; +} + +void +RadioEnvironmentMapHelper::SetBandwidth (uint8_t bw) +{ + switch (bw) + { + case 6: + case 15: + case 25: + case 50: + case 75: + case 100: + m_bandwidth = bw; + break; + + default: + NS_FATAL_ERROR ("invalid bandwidth value " << (uint16_t) bw); + break; + } +} + void @@ -138,66 +181,145 @@ RadioEnvironmentMapHelper::Install () m_channel = match.Get (0)->GetObject (); NS_ABORT_MSG_IF (m_channel == 0, "object at " << m_channelPath << "is not of type SpectrumChannel"); - double xStep = (m_xMax - m_xMin)/(m_xRes-1); - double yStep = (m_yMax - m_yMin)/(m_yRes-1); - - - for (double x = m_xMin; x < m_xMax + 0.5*xStep; x += xStep) - { - for (double y = m_yMin; y < m_yMax + 0.5*yStep ; y += yStep) - { - RemPoint p; - p.phy = CreateObject (); - p.bmm = CreateObject (); - p.phy->SetMobility (p.bmm); - p.bmm->SetPosition (Vector (x, y, m_z)); - BuildingsHelper::MakeConsistent (p.bmm); - m_rem.push_back (p); - } - } - Simulator::Schedule (Seconds (0.0055), &RadioEnvironmentMapHelper::Connect, this); - Simulator::Schedule (Seconds (0.0065), &RadioEnvironmentMapHelper::PrintAndDeactivate, this); - -} - -void -RadioEnvironmentMapHelper::Connect () -{ - NS_LOG_FUNCTION (this); - for (std::list::iterator it = m_rem.begin (); - it != m_rem.end (); - ++it) - { - NS_LOG_LOGIC ("adding phy " << it->phy); - m_channel->AddRx (it->phy); - } -} - -void -RadioEnvironmentMapHelper::PrintAndDeactivate () -{ - NS_LOG_FUNCTION (this); - std::ofstream outFile; - outFile.open (m_outputFile.c_str ()); - if (!outFile.is_open ()) + m_outFile.open (m_outputFile.c_str ()); + if (!m_outFile.is_open ()) { NS_FATAL_ERROR ("Can't open file " << (m_outputFile)); return; } + Simulator::Schedule (Seconds (0.0016), + &RadioEnvironmentMapHelper::DelayedInstall, + this); +} + + +void +RadioEnvironmentMapHelper::DelayedInstall () +{ + NS_LOG_FUNCTION (this); + m_xStep = (m_xMax - m_xMin)/(m_xRes-1); + m_yStep = (m_yMax - m_yMin)/(m_yRes-1); + + if ((double)m_xRes * (double) m_yRes < (double) m_maxPointsPerIteration) + { + m_maxPointsPerIteration = m_xRes * m_yRes; + } + + for (uint32_t i = 0; i < m_maxPointsPerIteration; ++i) + { + RemPoint p; + p.phy = CreateObject (); + p.bmm = CreateObject (); + p.phy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (m_earfcn, m_bandwidth)); + p.phy->SetMobility (p.bmm); + m_channel->AddRx (p.phy); + m_rem.push_back (p); + } + + double remIterationStartTime = 0.0001; + double xMinNext = m_xMin; + double yMinNext = m_yMin; + uint32_t numPointsCurrentIteration = 0; + bool justScheduled = false; + for (double x = m_xMin; x < m_xMax + 0.5*m_xStep; x += m_xStep) + { + for (double y = m_yMin; y < m_yMax + 0.5*m_yStep ; y += m_yStep) + { + if (justScheduled) + { + xMinNext = x; + yMinNext = y; + justScheduled = false; + } + + ++numPointsCurrentIteration; + if ((numPointsCurrentIteration == m_maxPointsPerIteration) + || ((x > m_xMax - 0.5*m_xStep) && (y > m_yMax - 0.5*m_yStep)) ) + { + Simulator::Schedule (Seconds (remIterationStartTime), + &RadioEnvironmentMapHelper::RunOneIteration, + this, xMinNext, x, yMinNext, y); + remIterationStartTime += 0.001; + justScheduled = true; + numPointsCurrentIteration = 0; + } + } + } + Simulator::Schedule (Seconds (remIterationStartTime), + &RadioEnvironmentMapHelper::Finalize, + this); +} + + +void +RadioEnvironmentMapHelper::RunOneIteration (double xMin, double xMax, double yMin, double yMax) +{ + NS_LOG_FUNCTION (this << xMin << xMax << yMin << yMax); + std::list::iterator remIt = m_rem.begin (); + double x; + double y; + for (x = xMin; x < xMax + 0.5*m_xStep; x += m_xStep) + { + for (y = (x == xMin) ? yMin : m_yMin; + y < ((x == xMax) ? yMax : m_yMax) + 0.5*m_yStep; + y += m_yStep) + { + NS_ASSERT (remIt != m_rem.end ()); + remIt->bmm->SetPosition (Vector (x, y, m_z)); + BuildingsHelper::MakeConsistent (remIt->bmm); + ++remIt; + } + } + + if (remIt != m_rem.end ()) + { + NS_ASSERT ((x > m_xMax - 0.5*m_xStep) && (y > m_yMax - 0.5*m_yStep)); + NS_LOG_LOGIC ("deactivating RemSpectrumPhys that are unneeded in the last iteration"); + while (remIt != m_rem.end ()) + { + remIt->phy->Deactivate (); + ++remIt; + } + } + + Simulator::Schedule (Seconds (0.0005), &RadioEnvironmentMapHelper::PrintAndReset, this); +} + +void +RadioEnvironmentMapHelper::PrintAndReset () +{ + NS_LOG_FUNCTION (this); + for (std::list::iterator it = m_rem.begin (); it != m_rem.end (); ++it) { + if (!(it->phy->IsActive ())) + { + // should occur only upon last iteration when some RemPoint + // at the end of the list can be unused + break; + } Vector pos = it->bmm->GetPosition (); - outFile << pos.x << "\t" - << pos.y << "\t" - << pos.z << "\t" - << it->phy->GetSinr (m_noisePower) - << std::endl; - it->phy->Deactivate (); + NS_LOG_LOGIC ("output: " << pos.x << "\t" + << pos.y << "\t" + << pos.z << "\t" + << it->phy->GetSinr (m_noisePower)); + m_outFile << pos.x << "\t" + << pos.y << "\t" + << pos.z << "\t" + << it->phy->GetSinr (m_noisePower) + << std::endl; + it->phy->Reset (); } - outFile.close (); +} + +void +RadioEnvironmentMapHelper::Finalize () +{ + NS_LOG_FUNCTION (this); + m_outFile.close (); if (m_stopWhenDone) { Simulator::Stop (); diff --git a/src/lte/helper/radio-environment-map-helper.h b/src/lte/helper/radio-environment-map-helper.h index 66e2f35e6..3b7080dd5 100644 --- a/src/lte/helper/radio-environment-map-helper.h +++ b/src/lte/helper/radio-environment-map-helper.h @@ -24,7 +24,7 @@ #include - +#include namespace ns3 { @@ -36,7 +36,7 @@ class SpectrumChannel; class BuildingsMobilityModel; /** - * Generates a 2D map of the SINR from the strongest transmitter. + * Generates a 2D map of the SINR from the strongest transmitter in the downlink of an LTE FDD system. * */ class RadioEnvironmentMapHelper : public Object @@ -44,19 +44,35 @@ class RadioEnvironmentMapHelper : public Object public: RadioEnvironmentMapHelper (); - virtual ~RadioEnvironmentMapHelper (); // inherited from Object virtual void DoDispose (void); static TypeId GetTypeId (void); + /** + * \return the bandwidth (in num of RBs) over which SINR is calculated + */ + uint8_t GetBandwidth () const; + + /** + * + * \param bw the bandwidth (in num of RBs) over which SINR is calculated + */ + void SetBandwidth (uint8_t bw); + + /** + * Deploy the RemSpectrumPhy objects that generate the map according to the specified settings. + * + */ void Install (); private: - void Connect (); - void PrintAndDeactivate (); + void DelayedInstall (); + void RunOneIteration (double xMin, double xMax, double yMin, double yMax); + void PrintAndReset (); + void Finalize (); struct RemPoint @@ -70,11 +86,18 @@ private: double m_xMin; double m_xMax; uint16_t m_xRes; + double m_xStep; double m_yMin; double m_yMax; uint16_t m_yRes; - + double m_yStep; + + uint32_t m_maxPointsPerIteration; + + uint16_t m_earfcn; + uint16_t m_bandwidth; + double m_z; std::string m_channelPath; @@ -85,6 +108,9 @@ private: Ptr m_channel; double m_noisePower; + + std::ofstream m_outFile; + }; diff --git a/src/lte/model/ideal-control-messages.cc b/src/lte/model/ideal-control-messages.cc index a2f14a507..cd17175e0 100644 --- a/src/lte/model/ideal-control-messages.cc +++ b/src/lte/model/ideal-control-messages.cc @@ -87,36 +87,6 @@ IdealControlMessage::GetMessageType (void) } - -// ---------------------------------------------------------------------------------------------------------- - -PdcchMapIdealControlMessage::PdcchMapIdealControlMessage (void) -{ - m_idealPdcchMessage = new IdealPdcchMessage (); - SetMessageType (IdealControlMessage::ALLOCATION_MAP); -} - - -PdcchMapIdealControlMessage::~PdcchMapIdealControlMessage (void) -{ - delete m_idealPdcchMessage; -} - -void -PdcchMapIdealControlMessage::AddNewRecord (Direction direction, - int subChannel, Ptr ue, double mcs) -{ - -} - - -PdcchMapIdealControlMessage::IdealPdcchMessage* -PdcchMapIdealControlMessage::GetMessage (void) -{ - return m_idealPdcchMessage; -} - - // ---------------------------------------------------------------------------------------------------------- diff --git a/src/lte/model/ideal-control-messages.h b/src/lte/model/ideal-control-messages.h index 836d27879..02d0c86d7 100644 --- a/src/lte/model/ideal-control-messages.h +++ b/src/lte/model/ideal-control-messages.h @@ -99,95 +99,6 @@ private: -// ---------------------------------------------------------------------------------------------------------- - - - -#ifndef PDCCH_MAP_IDEAL_CONTROL_MESSAGES_H -#define PDCCH_MAP_IDEAL_CONTROL_MESSAGES_H - -#include "ns3/object.h" -#include - -namespace ns3 { - -class LteNetDevice; - -/** - * \ingroup lte - * - * \brief The PdcchMapIdealControlMessage defines an ideal allocation map - * for both UL and DL sends by the eNodeB to all UE, - * using an ideal PDCCH control channel. - * IdealPdcchMessage is composed by a list of IdealPdcchRecord - * where is indicated the UE that can use a particular sub channel - * with a proper MCS scheme. - * This records are the same for both UL and DL, and are created by the - * packet scheduler at the beginning of each sub frame. - * When the IdealPdcchMessage is sent under an ideal control channel, - * all UE stores into a proper variables the informations about - * the resource mapping. - */ -class PdcchMapIdealControlMessage : public IdealControlMessage -{ -public: - PdcchMapIdealControlMessage (void); - virtual ~PdcchMapIdealControlMessage (void); - - /** - * Direction for which the message is created - */ - enum Direction - { - DOWNLINK, UPLINK - }; - - /** - * The PDCCH ideal record - */ - struct IdealPdcchRecord - { - /** the direction */ - Direction m_direction; - /** the sub channel */ - int m_idSubChannel; - /** the ue that receive the mapping */ - Ptr m_ue; - /** the selected msc */ - double m_mcsIndex; - }; - - /** - * The PDCCH ideal message - */ - typedef std::list IdealPdcchMessage; - - /** - * \brief add a PDCCH record into the message. - * \param direction the direction of the map - * \param subChannel the scheduled sub channel - * \param ue the ue the can use the sub channel for transmission - * \param mcs the selected MCS scheme - */ - void AddNewRecord (Direction direction, - int subChannel, Ptr ue, double mcs); - - /** - * \brief Get the message - * \return the pointer to the message - */ - IdealPdcchMessage* GetMessage (void); - -private: - IdealPdcchMessage *m_idealPdcchMessage; -}; - -} // namespace ns3 - -#endif /* PDCCH_MAP_IDEAL_CONTROL_MESSAGES_H */ - - - // ---------------------------------------------------------------------------------------------------------- @@ -201,9 +112,10 @@ private: namespace ns3 { /** -* The Downlink Data Control Indicator messages defines the RB allocation for the -* users -*/ + * \ingroup lte + * The Downlink Data Control Indicator messages defines the RB allocation for the + * users in the downlink + */ class DlDciIdealControlMessage : public IdealControlMessage { public: @@ -243,9 +155,10 @@ private: namespace ns3 { /** -* The Uplink Data Control Indicator messages defines the RB allocation for the -* users -*/ + * \ingroup lte + * The Uplink Data Control Indicator messages defines the RB allocation for the + * users in the uplink + */ class UlDciIdealControlMessage : public IdealControlMessage { public: @@ -289,9 +202,10 @@ namespace ns3 { class LteNetDevice; /** -* The downlink CqiIdealControlMessage defines an ideal list of -* feedback about the channel quality sent by the UE to the eNodeB. -*/ + * \ingroup lte + * The downlink CqiIdealControlMessage defines an ideal list of + * feedback about the channel quality sent by the UE to the eNodeB. + */ class DlCqiIdealControlMessage : public IdealControlMessage { public: @@ -332,9 +246,10 @@ namespace ns3 { class LteNetDevice; /** -* The uplink BsrIdealControlMessage defines the specific -* extension of the CE element for reporting the buffer status report -*/ + * \ingroup lte + * The uplink BsrIdealControlMessage defines the specific + * extension of the CE element for reporting the buffer status report + */ class BsrIdealControlMessage : public IdealControlMessage { public: diff --git a/src/lte/model/lte-enb-net-device.cc b/src/lte/model/lte-enb-net-device.cc index ee4aa8755..b2f9ac551 100644 --- a/src/lte/model/lte-enb-net-device.cc +++ b/src/lte/model/lte-enb-net-device.cc @@ -99,13 +99,13 @@ TypeId LteEnbNetDevice::GetTypeId (void) "as per 3GPP 36.101 Section 5.7.3. ", UintegerValue (100), MakeUintegerAccessor (&LteEnbNetDevice::m_dlEarfcn), - MakeUintegerChecker ()) + MakeUintegerChecker (0, 6149)) .AddAttribute ("UlEarfcn", "Uplink E-UTRA Absolute Radio Frequency Channel Number (EARFCN) " "as per 3GPP 36.101 Section 5.7.3. ", UintegerValue (18100), MakeUintegerAccessor (&LteEnbNetDevice::m_ulEarfcn), - MakeUintegerChecker ()) + MakeUintegerChecker (18000, 24149)) ; return tid; } diff --git a/src/lte/model/lte-spectrum-phy.cc b/src/lte/model/lte-spectrum-phy.cc index 8d07b4c63..3c55176d9 100644 --- a/src/lte/model/lte-spectrum-phy.cc +++ b/src/lte/model/lte-spectrum-phy.cc @@ -167,14 +167,7 @@ LteSpectrumPhy::SetChannel (Ptr c) Ptr LteSpectrumPhy::GetRxSpectrumModel () const { - if (m_txPsd) - { - return m_txPsd->GetSpectrumModel (); - } - else - { - return 0; - } + return m_rxSpectrumModel; } @@ -192,6 +185,7 @@ LteSpectrumPhy::SetNoisePowerSpectralDensity (Ptr noisePsd) { NS_LOG_FUNCTION (this << noisePsd); NS_ASSERT (noisePsd); + m_rxSpectrumModel = noisePsd->GetSpectrumModel (); m_interference->SetNoisePowerSpectralDensity (noisePsd); } diff --git a/src/lte/model/lte-spectrum-phy.h b/src/lte/model/lte-spectrum-phy.h index 202b6619e..a2a94a1a5 100644 --- a/src/lte/model/lte-spectrum-phy.h +++ b/src/lte/model/lte-spectrum-phy.h @@ -197,6 +197,7 @@ private: Ptr m_channel; + Ptr m_rxSpectrumModel; Ptr m_txPsd; Ptr m_txPacketBurst; std::list > m_rxPacketBurstList; diff --git a/src/lte/model/rem-spectrum-phy.cc b/src/lte/model/rem-spectrum-phy.cc index 5944ef271..b9681e442 100644 --- a/src/lte/model/rem-spectrum-phy.cc +++ b/src/lte/model/rem-spectrum-phy.cc @@ -105,8 +105,7 @@ RemSpectrumPhy::GetDevice () Ptr RemSpectrumPhy::GetRxSpectrumModel () const { - // supports any SpectrumModel - return 0; + return m_rxSpectrumModel; } Ptr @@ -133,6 +132,13 @@ RemSpectrumPhy::StartRx (Ptr params) } } +void +RemSpectrumPhy::SetRxSpectrumModel (Ptr m) +{ + NS_LOG_FUNCTION (this << m); + m_rxSpectrumModel = m; +} + double RemSpectrumPhy::GetSinr (double noisePower) { @@ -145,5 +151,18 @@ RemSpectrumPhy::Deactivate () m_active = false; } +bool +RemSpectrumPhy::IsActive () +{ + return m_active; +} + +void +RemSpectrumPhy::Reset () +{ + m_referenceSignalPower = 0; + m_sumPower = 0; +} + } // namespace ns3 diff --git a/src/lte/model/rem-spectrum-phy.h b/src/lte/model/rem-spectrum-phy.h index a22ba7336..cd6ac7e23 100644 --- a/src/lte/model/rem-spectrum-phy.h +++ b/src/lte/model/rem-spectrum-phy.h @@ -70,21 +70,39 @@ public: void StartRx (Ptr params); /** + * set the RX spectrum model to be used * + * \param m + */ + void SetRxSpectrumModel (Ptr m); + + /** * * \return the Signal to Noise Ratio calculated */ double GetSinr (double noisePower); /** - * make StartRx a no-op from now on + * make StartRx a no-op from now on, and mark instance as inactive * */ void Deactivate (); + /** + * + * \return true if active + */ + bool IsActive (); + + /** + * Reset the SINR calculator + * + */ + void Reset (); private: Ptr m_mobility; + Ptr m_rxSpectrumModel; double m_referenceSignalPower; double m_sumPower; diff --git a/src/lte/wscript b/src/lte/wscript index 6f6fa7970..72ffe7d16 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -39,6 +39,7 @@ def build(bld): 'helper/radio-bearer-stats-calculator.cc', 'helper/mac-stats-calculator.cc', 'helper/radio-environment-map-helper.cc', + 'helper/lte-hex-grid-enb-topology-helper.cc', 'model/rem-spectrum-phy.cc', 'model/ff-mac-csched-sap.cc', 'model/ff-mac-sched-sap.cc', @@ -132,6 +133,7 @@ def build(bld): 'helper/mac-stats-calculator.h', 'helper/radio-bearer-stats-calculator.h', 'helper/radio-environment-map-helper.h', + 'helper/lte-hex-grid-enb-topology-helper.h', 'model/rem-spectrum-phy.h', 'model/ff-mac-common.h', 'model/ff-mac-csched-sap.h',