diff -r 63903a9abcd2 src/devices/wifi/propagation-loss-model-test-suite.cc --- a/src/devices/wifi/propagation-loss-model-test-suite.cc Tue Dec 22 18:34:48 2009 +0300 +++ b/src/devices/wifi/propagation-loss-model-test-suite.cc Thu Jan 07 17:06:44 2010 +0000 @@ -145,6 +145,106 @@ return GetErrorStatus (); } +// Added for Two-Ray Ground Model - T.Hewer@cs.ucl.ac.uk + +class TwoRayGroundPropagationLossModelTestCase : public TestCase +{ +public: + TwoRayGroundPropagationLossModelTestCase (); + virtual ~TwoRayGroundPropagationLossModelTestCase (); + +private: + virtual bool DoRun (void); + + typedef struct { + Vector m_position; + double m_pt; // dBm + double m_pr; // W + double m_tolerance; + } TestVector; + + TestVectors m_testVectors; +}; + +TwoRayGroundPropagationLossModelTestCase::TwoRayGroundPropagationLossModelTestCase () +: TestCase ("Check to see that the ns-3 TwoRayGround propagation loss model provides correct received power"), m_testVectors () +{ +} + +TwoRayGroundPropagationLossModelTestCase::~TwoRayGroundPropagationLossModelTestCase () +{ +} + +bool +TwoRayGroundPropagationLossModelTestCase::DoRun (void) +{ + // wavelength at 2.4 GHz is 0.125m + Config::SetDefault ("ns3::TwoRayGroundPropagationLossModel::Lambda", DoubleValue (0.125)); + Config::SetDefault ("ns3::TwoRayGroundPropagationLossModel::SystemLoss", DoubleValue (1.0)); + + // Select a reference transmit power of 17.0206 dBm + // Pt = 10^(17.0206/10)/10^3 = .05035702 W + double txPowerW = 0.05035702; + double txPowerdBm = 10 * log10 (txPowerW) + 30; + + // + // As with the Friis tests above, we want to test the propagation loss + // model calculations at a few chosen distances and compare the results + // to those we can manually calculate. Let us test the ns-3 calculated + // value for agreement to be within 5e-16, as above. + // + TestVector testVector; + + // Below the Crossover distance use Friis so this test should be the same as that above + // Crossover = (4 * PI * RxAntennaHeight * RxAntennaHeight) / Lamdba + // Crossover = (4 * PI * 1.5 * 1.5) / 0.125 = 226.1946m + + testVector.m_position = Vector (100, 0, 0); + testVector.m_pt = txPowerdBm; + testVector.m_pr = 4.98265e-10; + testVector.m_tolerance = 5e-16; + m_testVectors.Add (testVector); + + // These values are above the crossover distance and therefore use the Two Ray calculation + + testVector.m_position = Vector (500, 0, 0); + testVector.m_pt = txPowerdBm; + testVector.m_pr = 4.07891862e-12; + testVector.m_tolerance = 5e-16; + m_testVectors.Add (testVector); + + testVector.m_position = Vector (1000, 0, 0); + testVector.m_pt = txPowerdBm; + testVector.m_pr = 2.5493241375e-13; + testVector.m_tolerance = 5e-16; + m_testVectors.Add (testVector); + + testVector.m_position = Vector (2000, 0, 0); + testVector.m_pt = txPowerdBm; + testVector.m_pr = 1.593327585938e-14; + testVector.m_tolerance = 5e-16; + m_testVectors.Add (testVector); + + // Now, check that the received power values are expected + + Ptr a = CreateObject (); + a->SetPosition (Vector (0,0,0)); + Ptr b = CreateObject (); + + Ptr lossModel = CreateObject (); + for (uint32_t i = 0; i < m_testVectors.GetN (); ++i) + { + testVector = m_testVectors.Get (i); + b->SetPosition (testVector.m_position); + double resultdBm = lossModel->CalcRxPower (testVector.m_pt, a, b); + double resultW = pow (10.0, resultdBm/10.0)/1000; + NS_TEST_EXPECT_MSG_EQ_TOL (resultW, testVector.m_pr, testVector.m_tolerance, "Got unexpected rcv power"); + } + + return GetErrorStatus (); +} + + class LogDistancePropagationLossModelTestCase : public TestCase { public: @@ -244,6 +344,7 @@ : TestSuite ("propagation-loss-model", UNIT) { AddTestCase (new FriisPropagationLossModelTestCase); + AddTestCase (new TwoRayGroundPropagationLossModelTestCase); AddTestCase (new LogDistancePropagationLossModelTestCase); } diff -r 63903a9abcd2 src/devices/wifi/propagation-loss-model.cc --- a/src/devices/wifi/propagation-loss-model.cc Tue Dec 22 18:34:48 2009 +0300 +++ b/src/devices/wifi/propagation-loss-model.cc Thu Jan 07 17:06:44 2010 +0000 @@ -17,6 +17,7 @@ * * Author: Mathieu Lacage * Contributions: Timo Bingmann + * Contributions: Tom Hewer for Two Ray Ground Model */ #include "propagation-loss-model.h" @@ -29,518 +30,697 @@ NS_LOG_COMPONENT_DEFINE ("PropagationLossModel"); namespace ns3 { - -// ------------------------------------------------------------------------- // - -NS_OBJECT_ENSURE_REGISTERED (PropagationLossModel); - -TypeId -PropagationLossModel::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::PropagationLossModel") - .SetParent () - ; - return tid; -} - -PropagationLossModel::PropagationLossModel () - : m_next (0) -{} - -PropagationLossModel::~PropagationLossModel () -{} - -void -PropagationLossModel::SetNext (Ptr next) -{ - m_next = next; -} - -double -PropagationLossModel::CalcRxPower (double txPowerDbm, - Ptr a, - Ptr b) const -{ - double self = DoCalcRxPower (txPowerDbm, a, b); - if (m_next != 0) - { - self = m_next->CalcRxPower (self, a, b); - } - return self; -} - -// ------------------------------------------------------------------------- // - -NS_OBJECT_ENSURE_REGISTERED (RandomPropagationLossModel); - -TypeId -RandomPropagationLossModel::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::RandomPropagationLossModel") - .SetParent () - .AddConstructor () - .AddAttribute ("Variable", "The random variable used to pick a loss everytime CalcRxPower is invoked.", - RandomVariableValue (ConstantVariable (1.0)), - MakeRandomVariableAccessor (&RandomPropagationLossModel::m_variable), - MakeRandomVariableChecker ()) - ; - return tid; -} -RandomPropagationLossModel::RandomPropagationLossModel () - : PropagationLossModel () -{} - -RandomPropagationLossModel::~RandomPropagationLossModel () -{} - -double -RandomPropagationLossModel::DoCalcRxPower (double txPowerDbm, - Ptr a, - Ptr b) const -{ - double rxc = -m_variable.GetValue (); - NS_LOG_DEBUG ("attenuation coefficent="< () - .AddConstructor () - .AddAttribute ("Lambda", - "The wavelength (default is 5.15 GHz at 300 000 km/s).", - DoubleValue (300000000.0 / 5.150e9), - MakeDoubleAccessor (&FriisPropagationLossModel::m_lambda), - MakeDoubleChecker ()) - .AddAttribute ("SystemLoss", "The system loss", - DoubleValue (1.0), - MakeDoubleAccessor (&FriisPropagationLossModel::m_systemLoss), - MakeDoubleChecker ()) - .AddAttribute ("MinDistance", - "The distance under which the propagation model refuses to give results (m)", - DoubleValue (0.5), - MakeDoubleAccessor (&FriisPropagationLossModel::SetMinDistance, - &FriisPropagationLossModel::GetMinDistance), - MakeDoubleChecker ()) - ; - return tid; -} - -FriisPropagationLossModel::FriisPropagationLossModel () -{} -void -FriisPropagationLossModel::SetSystemLoss (double systemLoss) -{ - m_systemLoss = systemLoss; -} -double -FriisPropagationLossModel::GetSystemLoss (void) const -{ - return m_systemLoss; -} -void -FriisPropagationLossModel::SetMinDistance (double minDistance) -{ - m_minDistance = minDistance; -} -double -FriisPropagationLossModel::GetMinDistance (void) const -{ - return m_minDistance; -} -void -FriisPropagationLossModel::SetLambda (double frequency, double speed) -{ - m_lambda = speed / frequency; -} -void -FriisPropagationLossModel::SetLambda (double lambda) -{ - m_lambda = lambda; -} -double -FriisPropagationLossModel::GetLambda (void) const -{ - return m_lambda; -} - -double -FriisPropagationLossModel::DbmToW (double dbm) const -{ - double mw = pow(10.0,dbm/10.0); - return mw / 1000.0; -} - -double -FriisPropagationLossModel::DbmFromW (double w) const -{ - double dbm = log10 (w * 1000.0) * 10.0; - return dbm; -} - -double -FriisPropagationLossModel::DoCalcRxPower (double txPowerDbm, - Ptr a, - Ptr b) const -{ - /* - * Friis free space equation: - * where Pt, Gr, Gr and P are in Watt units - * L is in meter units. - * - * P Gt * Gr * (lambda^2) - * --- = --------------------- - * Pt (4 * pi * d)^2 * L - * - * Gt: tx gain (unit-less) - * Gr: rx gain (unit-less) - * Pt: tx power (W) - * d: distance (m) - * L: system loss - * lambda: wavelength (m) - * - * Here, we ignore tx and rx gain and the input and output values - * are in dB or dBm: - * - * lambda^2 - * rx = tx + 10 log10 (-------------------) - * (4 * pi * d)^2 * L - * - * rx: rx power (dB) - * tx: tx power (dB) - * d: distance (m) - * L: system loss (unit-less) - * lambda: wavelength (m) - */ - double distance = a->GetDistanceFrom (b); - if (distance <= m_minDistance) - { - return txPowerDbm; - } - double numerator = m_lambda * m_lambda; - double denominator = 16 * PI * PI * distance * distance * m_systemLoss; - double pr = 10 * log10 (numerator / denominator); - NS_LOG_DEBUG ("distance="< () - .AddConstructor () - .AddAttribute ("Exponent", - "The exponent of the Path Loss propagation model", - DoubleValue (3.0), - MakeDoubleAccessor (&LogDistancePropagationLossModel::m_exponent), - MakeDoubleChecker ()) - .AddAttribute ("ReferenceDistance", - "The distance at which the reference loss is calculated (m)", - DoubleValue (1.0), - MakeDoubleAccessor (&LogDistancePropagationLossModel::m_referenceDistance), - MakeDoubleChecker ()) - .AddAttribute ("ReferenceLoss", - "The reference loss at reference distance (dB). (Default is Friis at 1m with 5.15 GHz)", - DoubleValue (46.6777), - MakeDoubleAccessor (&LogDistancePropagationLossModel::m_referenceLoss), - MakeDoubleChecker ()) - ; - return tid; - -} - -LogDistancePropagationLossModel::LogDistancePropagationLossModel () -{} - -void -LogDistancePropagationLossModel::SetPathLossExponent (double n) -{ - m_exponent = n; -} -void -LogDistancePropagationLossModel::SetReference (double referenceDistance, double referenceLoss) -{ - m_referenceDistance = referenceDistance; - m_referenceLoss = referenceLoss; -} -double -LogDistancePropagationLossModel::GetPathLossExponent (void) const -{ - return m_exponent; -} - -double -LogDistancePropagationLossModel::DoCalcRxPower (double txPowerDbm, - Ptr a, - Ptr b) const -{ - double distance = a->GetDistanceFrom (b); - if (distance <= m_referenceDistance) - { - return txPowerDbm; - } - /** - * The formula is: - * rx = 10 * log (Pr0(tx)) - n * 10 * log (d/d0) - * - * Pr0: rx power at reference distance d0 (W) - * d0: reference distance: 1.0 (m) - * d: distance (m) - * tx: tx power (dB) - * rx: dB - * - * Which, in our case is: - * - * rx = rx0(tx) - 10 * n * log (d/d0) - */ - double pathLossDb = 10 * m_exponent * log10 (distance / m_referenceDistance); - double rxc = -m_referenceLoss - pathLossDb; - NS_LOG_DEBUG ("distance="< () - .AddConstructor () - .AddAttribute ("Distance0", - "Beginning of the first (near) distance field", - DoubleValue (1.0), - MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_distance0), - MakeDoubleChecker ()) - .AddAttribute ("Distance1", - "Beginning of the second (middle) distance field.", - DoubleValue (200.0), - MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_distance1), - MakeDoubleChecker ()) - .AddAttribute ("Distance2", - "Beginning of the third (far) distance field.", - DoubleValue (500.0), - MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_distance2), - MakeDoubleChecker ()) - .AddAttribute ("Exponent0", - "The exponent for the first field.", - DoubleValue (1.9), - MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_exponent0), - MakeDoubleChecker ()) - .AddAttribute ("Exponent1", - "The exponent for the second field.", - DoubleValue (3.8), - MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_exponent1), - MakeDoubleChecker ()) - .AddAttribute ("Exponent2", - "The exponent for the third field.", - DoubleValue (3.8), - MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_exponent2), - MakeDoubleChecker ()) - .AddAttribute ("ReferenceLoss", - "The reference loss at distance d0 (dB). (Default is Friis at 1m with 5.15 GHz)", - DoubleValue (46.6777), - MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_referenceLoss), - MakeDoubleChecker ()) - ; - return tid; - -} - -ThreeLogDistancePropagationLossModel::ThreeLogDistancePropagationLossModel () -{ -} - -double -ThreeLogDistancePropagationLossModel::DoCalcRxPower (double txPowerDbm, - Ptr a, - Ptr b) const -{ - double distance = a->GetDistanceFrom (b); - NS_ASSERT(distance >= 0); - - // See doxygen comments for the formula and explanation - - double pathLossDb; - - if (distance < m_distance0) - { - pathLossDb = 0; - } - else if (distance < m_distance1) - { - pathLossDb = m_referenceLoss - + 10 * m_exponent0 * log10(distance / m_distance0); - } - else if (distance < m_distance2) - { - pathLossDb = m_referenceLoss - + 10 * m_exponent0 * log10(m_distance1 / m_distance0) - + 10 * m_exponent1 * log10(distance / m_distance1); - } - else - { - pathLossDb = m_referenceLoss - + 10 * m_exponent0 * log10(m_distance1 / m_distance0) - + 10 * m_exponent1 * log10(m_distance2 / m_distance1) - + 10 * m_exponent2 * log10(distance / m_distance2); - } - - NS_LOG_DEBUG ("ThreeLogDistance distance=" << distance << "m, " << - "attenuation=" << pathLossDb << "dB"); - - return txPowerDbm - pathLossDb; -} - -// ------------------------------------------------------------------------- // - -NS_OBJECT_ENSURE_REGISTERED (NakagamiPropagationLossModel); - -TypeId -NakagamiPropagationLossModel::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::NakagamiPropagationLossModel") - .SetParent () - .AddConstructor () - .AddAttribute ("Distance1", - "Beginning of the second distance field. Default is 80m.", - DoubleValue (80.0), - MakeDoubleAccessor (&NakagamiPropagationLossModel::m_distance1), - MakeDoubleChecker ()) - .AddAttribute ("Distance2", - "Beginning of the third distance field. Default is 200m.", - DoubleValue (200.0), - MakeDoubleAccessor (&NakagamiPropagationLossModel::m_distance2), - MakeDoubleChecker ()) - .AddAttribute ("m0", - "m0 for distances smaller than Distance1. Default is 1.5.", - DoubleValue (1.5), - MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m0), - MakeDoubleChecker ()) - .AddAttribute ("m1", - "m1 for distances smaller than Distance2. Default is 0.75.", - DoubleValue (0.75), - MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m1), - MakeDoubleChecker ()) - .AddAttribute ("m2", - "m2 for distances greater than Distance2. Default is 0.75.", - DoubleValue (0.75), - MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m2), - MakeDoubleChecker ()) - ; - return tid; - -} - -NakagamiPropagationLossModel::NakagamiPropagationLossModel () -{} - -double -NakagamiPropagationLossModel::DoCalcRxPower (double txPowerDbm, - Ptr a, - Ptr b) const -{ - // select m parameter - - double distance = a->GetDistanceFrom (b); - NS_ASSERT(distance >= 0); - - double m; - if (distance < m_distance1) - { - m = m_m0; - } - else if (distance < m_distance2) - { - m = m_m1; - } - else - { - m = m_m2; - } - - // the current power unit is dBm, but Watt is put into the Nakagami / - // Rayleigh distribution. - double powerW = pow(10, (txPowerDbm - 30) / 10); - - double resultPowerW; - - // switch between Erlang- and Gamma distributions: this is only for - // speed. (Gamma is equal to Erlang for any positive integer m.) - unsigned int int_m = static_cast(floor(m)); - - if (int_m == m) - { - resultPowerW = m_erlangRandomVariable.GetValue(int_m, powerW / m); - } - else - { - resultPowerW = m_gammaRandomVariable.GetValue(m, powerW / m); - } - - double resultPowerDbm = 10 * log10(resultPowerW) + 30; - - NS_LOG_DEBUG ("Nakagami distance=" << distance << "m, " << - "power=" << powerW <<"W, " << - "resultPower=" << resultPowerW << "W=" << resultPowerDbm << "dBm"); - - return resultPowerDbm; -} - -// ------------------------------------------------------------------------- // - -NS_OBJECT_ENSURE_REGISTERED (FixedRssLossModel); - -TypeId -FixedRssLossModel::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::FixedRssLossModel") - .SetParent () - .AddConstructor () - .AddAttribute ("Rss", "The fixed receiver Rss.", - DoubleValue (-150.0), - MakeDoubleAccessor (&FixedRssLossModel::m_rss), - MakeDoubleChecker ()) - ; - return tid; -} -FixedRssLossModel::FixedRssLossModel () - : PropagationLossModel () -{} - -FixedRssLossModel::~FixedRssLossModel () -{} - -void -FixedRssLossModel::SetRss (double rss) -{ - m_rss = rss; -} - -double -FixedRssLossModel::DoCalcRxPower (double txPowerDbm, - Ptr a, - Ptr b) const -{ - return m_rss; -} - -// ------------------------------------------------------------------------- // - + + // ------------------------------------------------------------------------- // + + NS_OBJECT_ENSURE_REGISTERED (PropagationLossModel); + + TypeId + PropagationLossModel::GetTypeId (void) + { + static TypeId tid = TypeId ("ns3::PropagationLossModel") + .SetParent () + ; + return tid; + } + + PropagationLossModel::PropagationLossModel () + : m_next (0) + {} + + PropagationLossModel::~PropagationLossModel () + {} + + void + PropagationLossModel::SetNext (Ptr next) + { + m_next = next; + } + + double + PropagationLossModel::CalcRxPower (double txPowerDbm, + Ptr a, + Ptr b) const + { + double self = DoCalcRxPower (txPowerDbm, a, b); + if (m_next != 0) + { + self = m_next->CalcRxPower (self, a, b); + } + return self; + } + + // ------------------------------------------------------------------------- // + + NS_OBJECT_ENSURE_REGISTERED (RandomPropagationLossModel); + + TypeId + RandomPropagationLossModel::GetTypeId (void) + { + static TypeId tid = TypeId ("ns3::RandomPropagationLossModel") + .SetParent () + .AddConstructor () + .AddAttribute ("Variable", "The random variable used to pick a loss everytime CalcRxPower is invoked.", + RandomVariableValue (ConstantVariable (1.0)), + MakeRandomVariableAccessor (&RandomPropagationLossModel::m_variable), + MakeRandomVariableChecker ()) + ; + return tid; + } + RandomPropagationLossModel::RandomPropagationLossModel () + : PropagationLossModel () + {} + + RandomPropagationLossModel::~RandomPropagationLossModel () + {} + + double + RandomPropagationLossModel::DoCalcRxPower (double txPowerDbm, + Ptr a, + Ptr b) const + { + double rxc = -m_variable.GetValue (); + NS_LOG_DEBUG ("attenuation coefficent="< () + .AddConstructor () + .AddAttribute ("Lambda", + "The wavelength (default is 5.15 GHz at 300 000 km/s).", + DoubleValue (300000000.0 / 5.150e9), + MakeDoubleAccessor (&FriisPropagationLossModel::m_lambda), + MakeDoubleChecker ()) + .AddAttribute ("SystemLoss", "The system loss", + DoubleValue (1.0), + MakeDoubleAccessor (&FriisPropagationLossModel::m_systemLoss), + MakeDoubleChecker ()) + .AddAttribute ("MinDistance", + "The distance under which the propagation model refuses to give results (m)", + DoubleValue (0.5), + MakeDoubleAccessor (&FriisPropagationLossModel::SetMinDistance, + &FriisPropagationLossModel::GetMinDistance), + MakeDoubleChecker ()) + ; + return tid; + } + + FriisPropagationLossModel::FriisPropagationLossModel () + {} + void + FriisPropagationLossModel::SetSystemLoss (double systemLoss) + { + m_systemLoss = systemLoss; + } + double + FriisPropagationLossModel::GetSystemLoss (void) const + { + return m_systemLoss; + } + void + FriisPropagationLossModel::SetMinDistance (double minDistance) + { + m_minDistance = minDistance; + } + double + FriisPropagationLossModel::GetMinDistance (void) const + { + return m_minDistance; + } + void + FriisPropagationLossModel::SetLambda (double frequency, double speed) + { + m_lambda = speed / frequency; + } + void + FriisPropagationLossModel::SetLambda (double lambda) + { + m_lambda = lambda; + } + double + FriisPropagationLossModel::GetLambda (void) const + { + return m_lambda; + } + + double + FriisPropagationLossModel::DbmToW (double dbm) const + { + double mw = pow(10.0,dbm/10.0); + return mw / 1000.0; + } + + double + FriisPropagationLossModel::DbmFromW (double w) const + { + double dbm = log10 (w * 1000.0) * 10.0; + return dbm; + } + + double + FriisPropagationLossModel::DoCalcRxPower (double txPowerDbm, + Ptr a, + Ptr b) const + { + /* + * Friis free space equation: + * where Pt, Gr, Gr and P are in Watt units + * L is in meter units. + * + * P Gt * Gr * (lambda^2) + * --- = --------------------- + * Pt (4 * pi * d)^2 * L + * + * Gt: tx gain (unit-less) + * Gr: rx gain (unit-less) + * Pt: tx power (W) + * d: distance (m) + * L: system loss + * lambda: wavelength (m) + * + * Here, we ignore tx and rx gain and the input and output values + * are in dB or dBm: + * + * lambda^2 + * rx = tx + 10 log10 (-------------------) + * (4 * pi * d)^2 * L + * + * rx: rx power (dB) + * tx: tx power (dB) + * d: distance (m) + * L: system loss (unit-less) + * lambda: wavelength (m) + */ + double distance = a->GetDistanceFrom (b); + if (distance <= m_minDistance) + { + return txPowerDbm; + } + double numerator = m_lambda * m_lambda; + double denominator = 16 * PI * PI * distance * distance * m_systemLoss; + double pr = 10 * log10 (numerator / denominator); + NS_LOG_DEBUG ("distance="< () + .AddConstructor () + .AddAttribute ("Lambda", + "The wavelength (default is 5.15 GHz at 300 000 km/s).", + DoubleValue (300000000.0 / 5.150e9), + MakeDoubleAccessor (&TwoRayGroundPropagationLossModel::m_lambda), + MakeDoubleChecker ()) + .AddAttribute ("SystemLoss", "The system loss", + DoubleValue (1.0), + MakeDoubleAccessor (&TwoRayGroundPropagationLossModel::m_systemLoss), + MakeDoubleChecker ()) + .AddAttribute ("MinDistance", + "The distance under which the propagation model refuses to give results (m)", + DoubleValue (0.5), + MakeDoubleAccessor (&TwoRayGroundPropagationLossModel::SetMinDistance, + &TwoRayGroundPropagationLossModel::GetMinDistance), + MakeDoubleChecker ()) + .AddAttribute ("TxAntHeight", + "The height of the transmitting antenna (m)", + DoubleValue (1.5), + MakeDoubleAccessor (&TwoRayGroundPropagationLossModel::m_txAntHeight), + MakeDoubleChecker ()) + .AddAttribute ("RxAntHeight", + "The height of the receiving antenna (m)", + DoubleValue (1.5), + MakeDoubleAccessor (&TwoRayGroundPropagationLossModel::m_rxAntHeight), + MakeDoubleChecker ()) + ; + return tid; + } + + TwoRayGroundPropagationLossModel::TwoRayGroundPropagationLossModel () + {} + void + TwoRayGroundPropagationLossModel::SetSystemLoss (double systemLoss) + { + m_systemLoss = systemLoss; + } + double + TwoRayGroundPropagationLossModel::GetSystemLoss (void) const + { + return m_systemLoss; + } + void + TwoRayGroundPropagationLossModel::SetMinDistance (double minDistance) + { + m_minDistance = minDistance; + } + double + TwoRayGroundPropagationLossModel::GetMinDistance (void) const + { + return m_minDistance; + } + void + TwoRayGroundPropagationLossModel::SetTxAntHeight (double txAntHeight) + { + m_txAntHeight = txAntHeight; + } + void + TwoRayGroundPropagationLossModel::SetRxAntHeight (double rxAntHeight) + { + m_rxAntHeight = rxAntHeight; + } + double + TwoRayGroundPropagationLossModel::GetTxAntHeight (void) const + { + return m_txAntHeight; + } + double + TwoRayGroundPropagationLossModel::GetRxAntHeight (void) const + { + return m_rxAntHeight; + } + void + TwoRayGroundPropagationLossModel::SetLambda (double frequency, double speed) + { + m_lambda = speed / frequency; + } + void + TwoRayGroundPropagationLossModel::SetLambda (double lambda) + { + m_lambda = lambda; + } + double + TwoRayGroundPropagationLossModel::GetLambda (void) const + { + return m_lambda; + } + + double + TwoRayGroundPropagationLossModel::DbmToW (double dbm) const + { + double mw = pow(10.0,dbm/10.0); + return mw / 1000.0; + } + + double + TwoRayGroundPropagationLossModel::DbmFromW (double w) const + { + double dbm = log10 (w * 1000.0) * 10.0; + return dbm; + } + + double + TwoRayGroundPropagationLossModel::DoCalcRxPower (double txPowerDbm, + Ptr a, + Ptr b) const + { + /* + * Two-Ray Ground equation: + * + * where Pt, Gt and Gr are in dBm units + * L, Ht and Hr are in meter units. + * + * Pr Gt * Gr * (Ht^2 * Hr^2) + * -- = (-------------------------) + * Pt d^4 * L + * + * Gt: tx gain (unit-less) + * Gr: rx gain (unit-less) + * Pt: tx power (dBm) + * d: distance (m) + * L: system loss + * Ht: Tx antenna height (m) + * Hr: Rx antenna height (m) + * lambda: wavelength (m) + * + * As with the Friis model we ignore tx and rx gain and output values + * are in dB or dBm + * + * (Ht * Ht) * (Hr * Hr) + * rx = tx + 10 log10 (-----------------------) + * (d * d * d * d) * L + */ + double distance = a->GetDistanceFrom (b); + if (distance <= m_minDistance) + { + return txPowerDbm; + } + + // Calculate a crossover distance, under which we use Friis + /* + * + * dCross = (4 * pi * Ht * Hr) / lambda + * + */ + + double dCross = (4 * PI * m_txAntHeight * m_rxAntHeight) / GetLambda(); + + if (distance <= dCross) { + // We use Friis + double numerator = m_lambda * m_lambda; + double denominator = 16 * PI * PI * distance * distance * m_systemLoss; + double pr = 10 * log10 (numerator / denominator); + NS_LOG_DEBUG ("Receiver within crossover ("< () + .AddConstructor () + .AddAttribute ("Exponent", + "The exponent of the Path Loss propagation model", + DoubleValue (3.0), + MakeDoubleAccessor (&LogDistancePropagationLossModel::m_exponent), + MakeDoubleChecker ()) + .AddAttribute ("ReferenceDistance", + "The distance at which the reference loss is calculated (m)", + DoubleValue (1.0), + MakeDoubleAccessor (&LogDistancePropagationLossModel::m_referenceDistance), + MakeDoubleChecker ()) + .AddAttribute ("ReferenceLoss", + "The reference loss at reference distance (dB). (Default is Friis at 1m with 5.15 GHz)", + DoubleValue (46.6777), + MakeDoubleAccessor (&LogDistancePropagationLossModel::m_referenceLoss), + MakeDoubleChecker ()) + ; + return tid; + + } + + LogDistancePropagationLossModel::LogDistancePropagationLossModel () + {} + + void + LogDistancePropagationLossModel::SetPathLossExponent (double n) + { + m_exponent = n; + } + void + LogDistancePropagationLossModel::SetReference (double referenceDistance, double referenceLoss) + { + m_referenceDistance = referenceDistance; + m_referenceLoss = referenceLoss; + } + double + LogDistancePropagationLossModel::GetPathLossExponent (void) const + { + return m_exponent; + } + + double + LogDistancePropagationLossModel::DoCalcRxPower (double txPowerDbm, + Ptr a, + Ptr b) const + { + double distance = a->GetDistanceFrom (b); + if (distance <= m_referenceDistance) + { + return txPowerDbm; + } + /** + * The formula is: + * rx = 10 * log (Pr0(tx)) - n * 10 * log (d/d0) + * + * Pr0: rx power at reference distance d0 (W) + * d0: reference distance: 1.0 (m) + * d: distance (m) + * tx: tx power (dB) + * rx: dB + * + * Which, in our case is: + * + * rx = rx0(tx) - 10 * n * log (d/d0) + */ + double pathLossDb = 10 * m_exponent * log10 (distance / m_referenceDistance); + double rxc = -m_referenceLoss - pathLossDb; + NS_LOG_DEBUG ("distance="< () + .AddConstructor () + .AddAttribute ("Distance0", + "Beginning of the first (near) distance field", + DoubleValue (1.0), + MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_distance0), + MakeDoubleChecker ()) + .AddAttribute ("Distance1", + "Beginning of the second (middle) distance field.", + DoubleValue (200.0), + MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_distance1), + MakeDoubleChecker ()) + .AddAttribute ("Distance2", + "Beginning of the third (far) distance field.", + DoubleValue (500.0), + MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_distance2), + MakeDoubleChecker ()) + .AddAttribute ("Exponent0", + "The exponent for the first field.", + DoubleValue (1.9), + MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_exponent0), + MakeDoubleChecker ()) + .AddAttribute ("Exponent1", + "The exponent for the second field.", + DoubleValue (3.8), + MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_exponent1), + MakeDoubleChecker ()) + .AddAttribute ("Exponent2", + "The exponent for the third field.", + DoubleValue (3.8), + MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_exponent2), + MakeDoubleChecker ()) + .AddAttribute ("ReferenceLoss", + "The reference loss at distance d0 (dB). (Default is Friis at 1m with 5.15 GHz)", + DoubleValue (46.6777), + MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_referenceLoss), + MakeDoubleChecker ()) + ; + return tid; + + } + + ThreeLogDistancePropagationLossModel::ThreeLogDistancePropagationLossModel () + { + } + + double + ThreeLogDistancePropagationLossModel::DoCalcRxPower (double txPowerDbm, + Ptr a, + Ptr b) const + { + double distance = a->GetDistanceFrom (b); + NS_ASSERT(distance >= 0); + + // See doxygen comments for the formula and explanation + + double pathLossDb; + + if (distance < m_distance0) + { + pathLossDb = 0; + } + else if (distance < m_distance1) + { + pathLossDb = m_referenceLoss + + 10 * m_exponent0 * log10(distance / m_distance0); + } + else if (distance < m_distance2) + { + pathLossDb = m_referenceLoss + + 10 * m_exponent0 * log10(m_distance1 / m_distance0) + + 10 * m_exponent1 * log10(distance / m_distance1); + } + else + { + pathLossDb = m_referenceLoss + + 10 * m_exponent0 * log10(m_distance1 / m_distance0) + + 10 * m_exponent1 * log10(m_distance2 / m_distance1) + + 10 * m_exponent2 * log10(distance / m_distance2); + } + + NS_LOG_DEBUG ("ThreeLogDistance distance=" << distance << "m, " << + "attenuation=" << pathLossDb << "dB"); + + return txPowerDbm - pathLossDb; + } + + // ------------------------------------------------------------------------- // + + NS_OBJECT_ENSURE_REGISTERED (NakagamiPropagationLossModel); + + TypeId + NakagamiPropagationLossModel::GetTypeId (void) + { + static TypeId tid = TypeId ("ns3::NakagamiPropagationLossModel") + .SetParent () + .AddConstructor () + .AddAttribute ("Distance1", + "Beginning of the second distance field. Default is 80m.", + DoubleValue (80.0), + MakeDoubleAccessor (&NakagamiPropagationLossModel::m_distance1), + MakeDoubleChecker ()) + .AddAttribute ("Distance2", + "Beginning of the third distance field. Default is 200m.", + DoubleValue (200.0), + MakeDoubleAccessor (&NakagamiPropagationLossModel::m_distance2), + MakeDoubleChecker ()) + .AddAttribute ("m0", + "m0 for distances smaller than Distance1. Default is 1.5.", + DoubleValue (1.5), + MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m0), + MakeDoubleChecker ()) + .AddAttribute ("m1", + "m1 for distances smaller than Distance2. Default is 0.75.", + DoubleValue (0.75), + MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m1), + MakeDoubleChecker ()) + .AddAttribute ("m2", + "m2 for distances greater than Distance2. Default is 0.75.", + DoubleValue (0.75), + MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m2), + MakeDoubleChecker ()) + ; + return tid; + + } + + NakagamiPropagationLossModel::NakagamiPropagationLossModel () + {} + + double + NakagamiPropagationLossModel::DoCalcRxPower (double txPowerDbm, + Ptr a, + Ptr b) const + { + // select m parameter + + double distance = a->GetDistanceFrom (b); + NS_ASSERT(distance >= 0); + + double m; + if (distance < m_distance1) + { + m = m_m0; + } + else if (distance < m_distance2) + { + m = m_m1; + } + else + { + m = m_m2; + } + + // the current power unit is dBm, but Watt is put into the Nakagami / + // Rayleigh distribution. + double powerW = pow(10, (txPowerDbm - 30) / 10); + + double resultPowerW; + + // switch between Erlang- and Gamma distributions: this is only for + // speed. (Gamma is equal to Erlang for any positive integer m.) + unsigned int int_m = static_cast(floor(m)); + + if (int_m == m) + { + resultPowerW = m_erlangRandomVariable.GetValue(int_m, powerW / m); + } + else + { + resultPowerW = m_gammaRandomVariable.GetValue(m, powerW / m); + } + + double resultPowerDbm = 10 * log10(resultPowerW) + 30; + + NS_LOG_DEBUG ("Nakagami distance=" << distance << "m, " << + "power=" << powerW <<"W, " << + "resultPower=" << resultPowerW << "W=" << resultPowerDbm << "dBm"); + + return resultPowerDbm; + } + + // ------------------------------------------------------------------------- // + + NS_OBJECT_ENSURE_REGISTERED (FixedRssLossModel); + + TypeId + FixedRssLossModel::GetTypeId (void) + { + static TypeId tid = TypeId ("ns3::FixedRssLossModel") + .SetParent () + .AddConstructor () + .AddAttribute ("Rss", "The fixed receiver Rss.", + DoubleValue (-150.0), + MakeDoubleAccessor (&FixedRssLossModel::m_rss), + MakeDoubleChecker ()) + ; + return tid; + } + FixedRssLossModel::FixedRssLossModel () + : PropagationLossModel () + {} + + FixedRssLossModel::~FixedRssLossModel () + {} + + void + FixedRssLossModel::SetRss (double rss) + { + m_rss = rss; + } + + double + FixedRssLossModel::DoCalcRxPower (double txPowerDbm, + Ptr a, + Ptr b) const + { + return m_rss; + } + + // ------------------------------------------------------------------------- // + } // namespace ns3 diff -r 63903a9abcd2 src/devices/wifi/propagation-loss-model.h --- a/src/devices/wifi/propagation-loss-model.h Tue Dec 22 18:34:48 2009 +0300 +++ b/src/devices/wifi/propagation-loss-model.h Thu Jan 07 17:06:44 2010 +0000 @@ -18,6 +18,7 @@ * Author: Mathieu Lacage * Contributions: Timo Bingmann * Contributions: Gary Pei for fixed RSS + * Contributions: Tom Hewer for porting Two Ray Ground */ #ifndef PROPAGATION_LOSS_MODEL_H @@ -181,8 +182,108 @@ double m_systemLoss; double m_minDistance; }; - -/** +/************************************************************************************ + * + * \brief a Two-Ray Ground propagation loss model ported from NS2 + * + * Two-ray ground reflection model. + * + * Pt * Gt * Gr * (ht^2 * hr^2) + * Pr = ---------------------------- + * d^4 * L + * + * The original equation in Rappaport's book assumes L = 1. + * To be consistant with the free space equation, L is added here. + * + * Ht and Hr are set by default to 1.5m + * + * The two-ray model does not give a good result for short distances, due to the + * oscillation caused by constructive and destructive combination of the two + * rays. Instead the Friis free-sapce model is used for small distances. */ + + class TwoRayGroundPropagationLossModel : public PropagationLossModel + { + public: + static TypeId GetTypeId (void); + TwoRayGroundPropagationLossModel (); + /** + * \param frequency (Hz) + * \param speed (m/s) + * + * Set the main wavelength used in the TwoRayGround model + * calculation. + */ + void SetLambda (double frequency, double speed); + /** + * \param lambda (m) the wavelength + * + * Set the main wavelength used in the TwoRayGround model + * calculation. + */ + void SetLambda (double lambda); + /** + * \param systemLoss (dimension-less) + * + * Set the system loss used by the TwoRayGround propagation model. + */ + void SetSystemLoss (double systemLoss); + + /** + * \param minDistance the minimum distance + * + * Below this distance, the txpower is returned + * unmodified as the rxpower. + */ + void SetMinDistance (double minDistance); + + /** + * \returns the minimum distance. + */ + double GetMinDistance (void) const; + + /** + * \returns the current wavelength (m) + */ + double GetLambda (void) const; + /** + * \returns the current system loss (dimention-less) + */ + double GetSystemLoss (void) const; + + /** + * \Set the Tx antenna height + */ + void SetTxAntHeight (double txAntHeight); + /** + * \Set the Rx antenna height + */ + void SetRxAntHeight (double rxAntHeight); + /** + * \Returns the Tx antenna height + */ + double GetTxAntHeight (void) const; + /** + * \Returns the Rx antenna height + */ + double GetRxAntHeight (void) const; + + private: + TwoRayGroundPropagationLossModel (const TwoRayGroundPropagationLossModel &o); + TwoRayGroundPropagationLossModel & operator = (const TwoRayGroundPropagationLossModel &o); + virtual double DoCalcRxPower (double txPowerDbm, + Ptr a, + Ptr b) const; + double DbmToW (double dbm) const; + double DbmFromW (double w) const; + + static const double PI; + double m_lambda; + double m_systemLoss; + double m_minDistance; + double m_txAntHeight; + double m_rxAntHeight; + }; +/**************************************************************************************************************** * \brief a log distance propagation model. * * This model calculates the reception power with a so-called