--- a/src/devices/wifi/propagation-loss-model-test-suite.cc Mon Jan 18 10:00:46 2010 +0100 +++ a/src/devices/wifi/propagation-loss-model-test-suite.cc Mon Jan 18 15:11:16 2010 +0000 @@ -145,6 +145,109 @@ return GetErrorStatus (); } +// Added for Two-Ray Ground Model - tomhewer@mac.com + +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)); + + // set antenna height to 1.5m above z coordinate + Config::SetDefault ("ns3::TwoRayGroundPropagationLossModel::HeightAboveZ", DoubleValue (1.5)); + + // 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 +347,7 @@ : TestSuite ("propagation-loss-model", UNIT) { AddTestCase (new FriisPropagationLossModelTestCase); + AddTestCase (new TwoRayGroundPropagationLossModelTestCase); AddTestCase (new LogDistancePropagationLossModelTestCase); } --- a/src/devices/wifi/propagation-loss-model.cc Mon Jan 18 10:00:46 2010 +0100 +++ a/src/devices/wifi/propagation-loss-model.cc Mon Jan 18 15:11:16 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" @@ -230,6 +231,173 @@ 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 ("HeightAboveZ", + "The height of the antenna (m) above the node's Z coordinate", + DoubleValue (0), + MakeDoubleAccessor (&TwoRayGroundPropagationLossModel::m_heightAboveZ), + 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::SetHeightAboveZ (double heightAboveZ) +{ + m_heightAboveZ = heightAboveZ; +} +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; + } + + // Set the height of the Tx and Rx antennae + Ptr txPosition = a->GetObject (); + Vector txPos = txPosition->GetPosition(); + double txAntHeight = txPos.z + m_heightAboveZ; + Ptr rxPosition = b->GetObject (); + Vector rxPos = rxPosition->GetPosition(); + double rxAntHeight = rxPos.z + m_heightAboveZ; + + // Calculate a crossover distance, under which we use Friis + /* + * + * dCross = (4 * pi * Ht * Hr) / lambda + * + */ + + double dCross = (4 * PI * txAntHeight * 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 ("< * Contributions: Timo Bingmann * Contributions: Gary Pei for fixed RSS + * Contributions: Tom Hewer for porting Two Ray Ground */ #ifndef PROPAGATION_LOSS_MODEL_H @@ -180,6 +181,95 @@ double m_lambda; double m_systemLoss; double m_minDistance; +}; + +/* + * + * \brief a Two-Ray Ground propagation loss model ported from NS2 + * + * Two-ray ground reflection model. + * + * \f$ Pr = \frac{Pt * Gt * Gr * (ht^2 * hr^2)}{d^4 * L} \f$ + * + * 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 at the respective nodes z coordinate plus a model parameter + * set via SetHeightAboveZ. + * + * 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-space model is used for small distances. + * + * The crossover distance, below which Friis is used, is calculated as follows: + * + * \f$ dCross = \frac{(4 * pi * Ht * Hr)}{lambda} \f$ + */ + +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 model antenna height above the node's Z coordinate + */ + void SetHeightAboveZ (double heightAboveZ); + +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_heightAboveZ; }; /**