From 176b697d20f541199dde79218c504c5b4893f170 Mon Sep 17 00:00:00 2001 From: Nicola Baldo Date: Tue, 5 Jul 2011 19:03:55 +0200 Subject: [PATCH] added support for single-freq PropagationLossModel to SpectrumChannel --- RELEASE_NOTES | 8 + ...ideal-phy-matrix-propagation-loss-model.cc | 151 +++++++++++ src/spectrum/examples/wscript | 4 + src/spectrum/helper/spectrum-helper.cc | 64 +++-- src/spectrum/helper/spectrum-helper.h | 53 +++- .../model/multi-model-spectrum-channel.cc | 83 +++--- .../model/multi-model-spectrum-channel.h | 18 +- .../model/single-model-spectrum-channel.cc | 89 ++++--- .../model/single-model-spectrum-channel.h | 19 +- src/spectrum/model/spectrum-channel.h | 13 +- src/spectrum/test/examples-to-run.py | 1 + src/spectrum/test/spectrum-ideal-phy-test.cc | 245 ++++++++++++++++++ src/spectrum/wscript | 1 + 13 files changed, 648 insertions(+), 101 deletions(-) create mode 100644 src/spectrum/examples/adhoc-aloha-ideal-phy-matrix-propagation-loss-model.cc create mode 100644 src/spectrum/test/spectrum-ideal-phy-test.cc diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 5d770e1e8..44591da71 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -21,6 +21,14 @@ Supported platforms New user-visible features ------------------------- +- SpectrumChannel models now support the usage of single-frequency + propagation loss models based on the PropagationLossModel + class. These model can be used in conjunction with + the frequency-dependent propagation loss model based on the + SpectrumPropagationLossModel class already supported by + SpectrumChannel. + + Bugs fixed ---------- - bug 1033 - Mesh airtime-metric fixed diff --git a/src/spectrum/examples/adhoc-aloha-ideal-phy-matrix-propagation-loss-model.cc b/src/spectrum/examples/adhoc-aloha-ideal-phy-matrix-propagation-loss-model.cc new file mode 100644 index 000000000..44f143db3 --- /dev/null +++ b/src/spectrum/examples/adhoc-aloha-ideal-phy-matrix-propagation-loss-model.cc @@ -0,0 +1,151 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +NS_LOG_COMPONENT_DEFINE ("TestAdhocOfdmAloha"); + +using namespace ns3; + +static bool g_verbose = false; +static uint64_t g_rxBytes; + +void +PhyRxEndOkTrace (std::string context, Ptr p) +{ + if (g_verbose) + { + std::cout << context << " PHY RX END OK p:" << p << std::endl; + } + g_rxBytes += p->GetSize (); +} + + +int main (int argc, char** argv) +{ + CommandLine cmd; + double lossDb; + double txPowerW = 0.1; + uint64_t phyRate = 500000; + uint32_t pktSize = 1000; + cmd.AddValue ("verbose", "Print trace information if true", g_verbose); + cmd.AddValue ("lossDb", "link loss in dB", lossDb); + cmd.AddValue ("txPowerW", "txPower in Watts", txPowerW); + cmd.AddValue ("phyRate", "PHY rate in bps", phyRate); + cmd.AddValue ("pktSize", "packet size in bytes", pktSize); + cmd.Parse (argc, argv); + + NodeContainer c; + c.Create (2); + + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector (0.0, 0.0, 0.0)); + positionAlloc->Add (Vector (5.0, 0.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + + + mobility.Install (c); + + + SpectrumChannelHelper channelHelper; + channelHelper.SetChannel ("ns3::MultiModelSpectrumChannel"); + channelHelper.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel"); + Ptr propLoss = CreateObject (); + propLoss->SetLoss (c.Get (0)->GetObject (), c.Get (1)->GetObject (), lossDb, true); + channelHelper.AddPropagationLoss (propLoss); + Ptr channel = channelHelper.Create (); + + + WifiSpectrumValue5MhzFactory sf; + + uint32_t channelNumber = 1; + Ptr txPsd = sf.CreateTxPowerSpectralDensity (txPowerW, channelNumber); + + // for the noise, we use the Power Spectral Density of thermal noise + // at room temperature. The value of the PSD will be constant over the band of interest. + const double k = 1.381e-23; //Boltzmann's constant + const double T = 290; // temperature in Kelvin + double noisePsdValue = k * T; // watts per hertz + Ptr noisePsd = sf.CreateConstant (noisePsdValue); + + AdhocAlohaNoackIdealPhyHelper deviceHelper; + deviceHelper.SetChannel (channel); + deviceHelper.SetTxPowerSpectralDensity (txPsd); + deviceHelper.SetNoisePowerSpectralDensity (noisePsd); + deviceHelper.SetPhyAttribute ("Rate", DataRateValue (DataRate (phyRate))); + NetDeviceContainer devices = deviceHelper.Install (c); + + PacketSocketHelper packetSocket; + packetSocket.Install (c); + + PacketSocketAddress socket; + socket.SetSingleDevice (devices.Get (0)->GetIfIndex ()); + socket.SetPhysicalAddress (devices.Get (1)->GetAddress ()); + socket.SetProtocol (1); + + OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket)); + onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (250))); + onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0))); + onoff.SetAttribute ("DataRate", DataRateValue (DataRate (2*phyRate))); + onoff.SetAttribute ("PacketSize", UintegerValue (pktSize)); + + ApplicationContainer apps = onoff.Install (c.Get (0)); + apps.Start (Seconds (0.0)); + apps.Stop (Seconds (10.0)); + + Config::Connect ("/NodeList/*/DeviceList/*/Phy/RxEndOk", MakeCallback (&PhyRxEndOkTrace)); + + g_rxBytes = 0; + Simulator::Stop (Seconds (10.0001)); + Simulator::Run (); + double throughputBps = (g_rxBytes * 8.0) / 10.0; + + std::cerr << "throughput: " << std::setw (20) << std::fixed << throughputBps << " bps" << std::endl; + std::cerr << "phy rate : " << std::setw (20) << std::fixed << phyRate*1.0 << " bps" << std::endl; + double rxPowerW = txPowerW / (pow (10.0, lossDb/10.0)); + double capacity = 20e6*log2 (1.0 + (rxPowerW/20.0e6)/noisePsdValue); + std::cerr << "shannon capacity: " << std::setw (20) << std::fixed << capacity << " bps" << std::endl; + + + Simulator::Destroy (); + return 0; +} diff --git a/src/spectrum/examples/wscript b/src/spectrum/examples/wscript index 3b369eb0e..27deedb91 100644 --- a/src/spectrum/examples/wscript +++ b/src/spectrum/examples/wscript @@ -5,6 +5,10 @@ def build(bld): ['spectrum', 'mobility']) obj.source = 'adhoc-aloha-ideal-phy.cc' + obj = bld.create_ns3_program('adhoc-aloha-ideal-phy-matrix-propagation-loss-model', + ['spectrum', 'mobility']) + obj.source = 'adhoc-aloha-ideal-phy-matrix-propagation-loss-model.cc' + obj = bld.create_ns3_program('adhoc-aloha-ideal-phy-with-microwave-oven', ['spectrum', 'mobility']) obj.source = 'adhoc-aloha-ideal-phy-with-microwave-oven.cc' diff --git a/src/spectrum/helper/spectrum-helper.cc b/src/spectrum/helper/spectrum-helper.cc index 7c3714558..53f9fff67 100644 --- a/src/spectrum/helper/spectrum-helper.cc +++ b/src/spectrum/helper/spectrum-helper.cc @@ -21,8 +21,6 @@ #include #include #include -#include -#include #include #include #include @@ -66,6 +64,38 @@ SpectrumChannelHelper::SetChannel (std::string type, m_channel.Set (n7, v7); } +void +SpectrumChannelHelper::AddPropagationLoss (std::string type, + std::string n0, const AttributeValue &v0, + std::string n1, const AttributeValue &v1, + std::string n2, const AttributeValue &v2, + std::string n3, const AttributeValue &v3, + std::string n4, const AttributeValue &v4, + std::string n5, const AttributeValue &v5, + std::string n6, const AttributeValue &v6, + std::string n7, const AttributeValue &v7) +{ + ObjectFactory factory; + factory.SetTypeId (type); + factory.Set (n0, v0); + factory.Set (n1, v1); + factory.Set (n2, v2); + factory.Set (n3, v3); + factory.Set (n4, v4); + factory.Set (n5, v5); + factory.Set (n6, v6); + factory.Set (n7, v7); + Ptr m = factory.Create (); + AddPropagationLoss (m); +} + + +void +SpectrumChannelHelper::AddPropagationLoss (Ptr m) +{ + m->SetNext (m_propagationLossModel); + m_propagationLossModel = m; +} void SpectrumChannelHelper::AddSpectrumPropagationLoss (std::string type, @@ -88,7 +118,15 @@ SpectrumChannelHelper::AddSpectrumPropagationLoss (std::string type, factory.Set (n5, v5); factory.Set (n6, v6); factory.Set (n7, v7); - m_spectrumPropagationLoss.push_back (factory); + Ptr m = factory.Create (); + AddSpectrumPropagationLoss (m); +} + +void +SpectrumChannelHelper::AddSpectrumPropagationLoss (Ptr m) +{ + m->SetNext (m_spectrumPropagationLossModel); + m_spectrumPropagationLossModel = m; } void @@ -119,30 +157,14 @@ Ptr SpectrumChannelHelper::Create (void) const { Ptr channel = (m_channel.Create ())->GetObject (); - Ptr prev = 0; - for (std::vector::const_iterator i = m_spectrumPropagationLoss.begin (); i != m_spectrumPropagationLoss.end (); ++i) - { - Ptr cur = (*i).Create (); - if (prev == 0) - { - channel->AddSpectrumPropagationLossModel (cur); - } - else - { - prev->SetNext (cur); - } - prev = cur; - } + channel->AddSpectrumPropagationLossModel (m_spectrumPropagationLossModel); + channel->AddPropagationLossModel (m_propagationLossModel); Ptr delay = m_propagationDelay.Create (); channel->SetPropagationDelayModel (delay); return channel; } - - - - void SpectrumPhyHelper::SetPhy (std::string type, std::string n0, const AttributeValue &v0, diff --git a/src/spectrum/helper/spectrum-helper.h b/src/spectrum/helper/spectrum-helper.h index f2cdf344d..41dc68ea5 100644 --- a/src/spectrum/helper/spectrum-helper.h +++ b/src/spectrum/helper/spectrum-helper.h @@ -26,6 +26,8 @@ #include #include #include +#include +#include namespace ns3 { @@ -72,6 +74,44 @@ public: std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (), std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (), std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ()); + /** + * \param name the name of the model to set + * \param n0 the name of the attribute to set + * \param v0 the value of the attribute to set + * \param n1 the name of the attribute to set + * \param v1 the value of the attribute to set + * \param n2 the name of the attribute to set + * \param v2 the value of the attribute to set + * \param n3 the name of the attribute to set + * \param v3 the value of the attribute to set + * \param n4 the name of the attribute to set + * \param v4 the value of the attribute to set + * \param n5 the name of the attribute to set + * \param v5 the value of the attribute to set + * \param n6 the name of the attribute to set + * \param v6 the value of the attribute to set + * \param n7 the name of the attribute to set + * \param v7 the value of the attribute to set + * + * Add a new single-frequency propagation loss model to this channel helper. + */ + void AddPropagationLoss (std::string name, + std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (), + std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (), + std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (), + std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (), + std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (), + std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (), + std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (), + std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ()); + + + /** + * Add a new single-frequency propagation loss model instance to this channel helper. + * + * \param m a pointer to the instance of the propagation loss model + */ + void AddPropagationLoss (Ptr m); /** * \param name the name of the model to set @@ -92,7 +132,7 @@ public: * \param n7 the name of the attribute to set * \param v7 the value of the attribute to set * - * Add a new spectrum propagation loss to this channel helper. + * Add a new frequency-dependent propagation loss model to this channel helper. */ void AddSpectrumPropagationLoss (std::string name, std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (), @@ -103,6 +143,14 @@ public: std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (), std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (), std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ()); + + /** + * Add a new frequency-dependent propagation loss model instance to this channel helper. + * + * \param m a pointer to the instance of the propagation loss model + */ + void AddSpectrumPropagationLoss (Ptr m); + /** * \param name the name of the model to set * \param n0 the name of the attribute to set @@ -142,7 +190,8 @@ public: Ptr Create (void) const; private: - std::vector m_spectrumPropagationLoss; + Ptr m_spectrumPropagationLossModel; + Ptr m_propagationLossModel; ObjectFactory m_propagationDelay; ObjectFactory m_channel; }; diff --git a/src/spectrum/model/multi-model-spectrum-channel.cc b/src/spectrum/model/multi-model-spectrum-channel.cc index cd6a4cf49..5bddf80b5 100644 --- a/src/spectrum/model/multi-model-spectrum-channel.cc +++ b/src/spectrum/model/multi-model-spectrum-channel.cc @@ -25,9 +25,13 @@ #include #include #include +#include #include #include #include +#include +#include +#include #include #include #include "multi-model-spectrum-channel.h" @@ -72,8 +76,6 @@ RxSpectrumModelInfo::RxSpectrumModelInfo (Ptr rxSpectrumMod MultiModelSpectrumChannel::MultiModelSpectrumChannel () - : m_PropagationDelay (0), - m_PropagationLoss (0) { NS_LOG_FUNCTION (this); } @@ -82,8 +84,9 @@ void MultiModelSpectrumChannel::DoDispose () { NS_LOG_FUNCTION (this); - m_PropagationLoss = 0; - m_PropagationDelay = 0; + m_propagationDelay = 0; + m_propagationLoss = 0; + m_spectrumPropagationLoss = 0; m_txSpectrumModelInfoMap.clear (); m_rxSpectrumModelInfoMap.clear (); m_phyVector.clear (); @@ -96,6 +99,18 @@ MultiModelSpectrumChannel::GetTypeId (void) static TypeId tid = TypeId ("ns3::MultiModelSpectrumChannel") .SetParent () .AddConstructor () + .AddAttribute ("MaxLossDb", + "If a single-frequency PropagationLossModel is used, this value " + "represents the maximum loss in dB for which transmissions will be " + "passed to the receiving PHY. Signals for which the PropagationLossModel " + "returns a loss bigger than this value will not be propagated to the receiver. " + "This parameter is to be used to reduce " + "the computational load by not propagating signals that are far beyond " + "the interference range. Note that the default value corresponds to " + "considering all signals for reception. Tune this value with care. ", + DoubleValue (1.0e9), + MakeDoubleAccessor (&MultiModelSpectrumChannel::m_maxLossDb), + MakeDoubleChecker ()) ; return tid; } @@ -241,45 +256,44 @@ MultiModelSpectrumChannel::StartTx (Ptr p, Ptr orig convertedTxPowerSpectrum = rxConverterIterator->second.Convert (originalTxPowerSpectrum); } - std::list >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhyList.begin (); - while (rxPhyIterator != rxInfoIterator->second.m_rxPhyList.end ()) + for (std::list >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhyList.begin (); + rxPhyIterator != rxInfoIterator->second.m_rxPhyList.end (); + ++rxPhyIterator) { NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid, "MultiModelSpectrumChannel only supports devices that use a single RxSpectrumModel that does not change for the whole simulation"); if ((*rxPhyIterator) != txPhy) { - Ptr rxPowerSpectrum; - Time delay; + Ptr rxPowerSpectrum = convertedTxPowerSpectrum->Copy (); + Time delay = MicroSeconds (0); + Ptr receiverMobility = (*rxPhyIterator)->GetMobility ()->GetObject (); if (txMobility && receiverMobility) { - if (m_PropagationLoss) + if (m_propagationLoss) { - rxPowerSpectrum = m_PropagationLoss->CalcRxPowerSpectralDensity (convertedTxPowerSpectrum, txMobility, receiverMobility); - } - else - { - // rxPowerSpectrum = Copy (convertedTxPowerSpectrum); - rxPowerSpectrum = convertedTxPowerSpectrum->Copy (); + double gainDb = m_propagationLoss->CalcRxPower (0, txMobility, receiverMobility); + if ( (-gainDb) > m_maxLossDb) + { + // beyond range + continue; + } + double gainLinear = pow (10.0, gainDb/10.0); + *rxPowerSpectrum = (*rxPowerSpectrum) * gainLinear; } - if (m_PropagationDelay) + if (m_spectrumPropagationLoss) { - delay = m_PropagationDelay->GetDelay (txMobility, receiverMobility); + rxPowerSpectrum = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity (rxPowerSpectrum, txMobility, receiverMobility); } - else + + if (m_propagationDelay) { - delay = MicroSeconds (0); + delay = m_propagationDelay->GetDelay (txMobility, receiverMobility); } } - else - { - // rxPowerSpectrum = Copy (convertedTxPowerSpectrum); - rxPowerSpectrum = convertedTxPowerSpectrum->Copy (); - delay = MicroSeconds (0); - } Ptr pktBurstCopy = p->Copy (); Ptr netDevObj = (*rxPhyIterator)->GetDevice (); @@ -297,7 +311,6 @@ MultiModelSpectrumChannel::StartTx (Ptr p, Ptr orig pktBurstCopy, rxPowerSpectrum, st, duration, *rxPhyIterator); } } - ++rxPhyIterator; } } @@ -329,25 +342,33 @@ MultiModelSpectrumChannel::GetDevice (uint32_t i) const +void +MultiModelSpectrumChannel::AddPropagationLossModel (Ptr loss) +{ + NS_LOG_FUNCTION (this << loss); + NS_ASSERT (m_propagationLoss == 0); + m_propagationLoss = loss; +} + void MultiModelSpectrumChannel::AddSpectrumPropagationLossModel (Ptr loss) { - NS_ASSERT (m_PropagationLoss == 0); - m_PropagationLoss = loss; + NS_ASSERT (m_propagationLoss == 0); + m_spectrumPropagationLoss = loss; } void MultiModelSpectrumChannel::SetPropagationDelayModel (Ptr delay) { - NS_ASSERT (m_PropagationDelay == 0); - m_PropagationDelay = delay; + NS_ASSERT (m_propagationDelay == 0); + m_propagationDelay = delay; } Ptr MultiModelSpectrumChannel::GetSpectrumPropagationLossModel (void) { NS_LOG_FUNCTION (this); - return m_PropagationLoss; + return m_spectrumPropagationLoss; } diff --git a/src/spectrum/model/multi-model-spectrum-channel.h b/src/spectrum/model/multi-model-spectrum-channel.h index 0f5f12e81..2720353d2 100644 --- a/src/spectrum/model/multi-model-spectrum-channel.h +++ b/src/spectrum/model/multi-model-spectrum-channel.h @@ -88,6 +88,7 @@ public: static TypeId GetTypeId (void); // inherited from SpectrumChannel + virtual void AddPropagationLossModel (Ptr loss); virtual void AddSpectrumPropagationLossModel (Ptr loss); virtual void SetPropagationDelayModel (Ptr delay); virtual void AddRx (Ptr phy); @@ -147,15 +148,19 @@ private: * propagation delay model to be used with this channel * */ - Ptr m_PropagationDelay; - + Ptr m_propagationDelay; /** - * propagation loss model to be used with this channel + * single-frequency propagation loss model to be used with this channel + * + */ + Ptr m_propagationLoss; + + /** + * frequency-dependent propagation loss model to be used with this channel * */ - Ptr m_PropagationLoss; - + Ptr m_spectrumPropagationLoss; /** @@ -180,6 +185,9 @@ private: * */ std::vector > m_phyVector; + + + double m_maxLossDb; }; diff --git a/src/spectrum/model/single-model-spectrum-channel.cc b/src/spectrum/model/single-model-spectrum-channel.cc index 025dd8051..9426296e8 100644 --- a/src/spectrum/model/single-model-spectrum-channel.cc +++ b/src/spectrum/model/single-model-spectrum-channel.cc @@ -25,8 +25,14 @@ #include #include #include +#include #include #include +#include +#include +#include + + #include "single-model-spectrum-channel.h" @@ -39,9 +45,6 @@ namespace ns3 { NS_OBJECT_ENSURE_REGISTERED (SingleModelSpectrumChannel); SingleModelSpectrumChannel::SingleModelSpectrumChannel () - : m_spectrumModel (0), - m_PropagationDelay (0), - m_PropagationLoss (0) { NS_LOG_FUNCTION (this); } @@ -52,8 +55,9 @@ SingleModelSpectrumChannel::DoDispose () NS_LOG_FUNCTION (this); m_phyList.clear (); m_spectrumModel = 0; - m_PropagationDelay = 0; - m_PropagationLoss = 0; + m_propagationDelay = 0; + m_propagationLoss = 0; + m_spectrumPropagationLoss = 0; SpectrumChannel::DoDispose (); } @@ -64,6 +68,18 @@ SingleModelSpectrumChannel::GetTypeId (void) static TypeId tid = TypeId ("ns3::SingleModelSpectrumChannel") .SetParent () .AddConstructor () + .AddAttribute ("MaxLossDb", + "If a single-frequency PropagationLossModel is used, this value " + "represents the maximum loss in dB for which transmissions will be " + "passed to the receiving PHY. Signals for which the PropagationLossModel " + "returns a loss bigger than this value will not be propagated to the receiver. " + "This parameter is to be used to reduce " + "the computational load by not propagating signals that are far beyond " + "the interference range. Note that the default value corresponds to " + "considering all signals for reception. Tune this value with care. ", + DoubleValue (1.0e9), + MakeDoubleAccessor (&SingleModelSpectrumChannel::m_maxLossDb), + MakeDoubleChecker ()) ; return tid; } @@ -98,47 +114,45 @@ SingleModelSpectrumChannel::StartTx (Ptr p, Ptr txP } - PhyList::const_iterator rxPhyIterator = m_phyList.begin (); + Ptr senderMobility = txPhy->GetMobility ()->GetObject (); - NS_ASSERT (rxPhyIterator != m_phyList.end ()); - - while (rxPhyIterator != m_phyList.end ()) + for (PhyList::const_iterator rxPhyIterator = m_phyList.begin (); + rxPhyIterator != m_phyList.end (); + ++rxPhyIterator) { if ((*rxPhyIterator) != txPhy) { - Ptr rxPsd; - Time delay; + Ptr rxPsd = Copy (txPsd); + Time delay = MicroSeconds (0); + Ptr receiverMobility = (*rxPhyIterator)->GetMobility ()->GetObject (); if (senderMobility && receiverMobility) { - - - if (m_PropagationLoss) + if (m_propagationLoss) { - rxPsd = m_PropagationLoss->CalcRxPowerSpectralDensity (txPsd, senderMobility, receiverMobility); - } - else - { - rxPsd = txPsd; + double gainDb = m_propagationLoss->CalcRxPower (0, senderMobility, receiverMobility); + if ( (-gainDb) > m_maxLossDb) + { + // beyond range + continue; + } + double gainLinear = pow (10.0, gainDb/10.0); + *rxPsd = (*rxPsd) * gainLinear; } - if (m_PropagationDelay) + if (m_spectrumPropagationLoss) { - delay = m_PropagationDelay->GetDelay (senderMobility, receiverMobility); + rxPsd = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity (rxPsd, senderMobility, receiverMobility); } - else + + if (m_propagationDelay) { - delay = MicroSeconds (0); + delay = m_propagationDelay->GetDelay (senderMobility, receiverMobility); } } - else - { - rxPsd = txPsd; - delay = MicroSeconds (0); - } Ptr pktBurstCopy = p->Copy (); Ptr netDevObj = (*rxPhyIterator)->GetDevice (); @@ -156,7 +170,6 @@ SingleModelSpectrumChannel::StartTx (Ptr p, Ptr txP pktBurstCopy, rxPsd, st, duration, *rxPhyIterator); } } - ++rxPhyIterator; } } @@ -186,21 +199,29 @@ SingleModelSpectrumChannel::GetDevice (uint32_t i) const } +void +SingleModelSpectrumChannel::AddPropagationLossModel (Ptr loss) +{ + NS_LOG_FUNCTION (this << loss); + NS_ASSERT (m_propagationLoss == 0); + m_propagationLoss = loss; +} + void SingleModelSpectrumChannel::AddSpectrumPropagationLossModel (Ptr loss) { NS_LOG_FUNCTION (this << loss); - NS_ASSERT (m_PropagationLoss == 0); - m_PropagationLoss = loss; + NS_ASSERT (m_propagationLoss == 0); + m_spectrumPropagationLoss = loss; } void SingleModelSpectrumChannel::SetPropagationDelayModel (Ptr delay) { NS_LOG_FUNCTION (this << delay); - NS_ASSERT (m_PropagationDelay == 0); - m_PropagationDelay = delay; + NS_ASSERT (m_propagationDelay == 0); + m_propagationDelay = delay; } @@ -208,7 +229,7 @@ Ptr SingleModelSpectrumChannel::GetSpectrumPropagationLossModel (void) { NS_LOG_FUNCTION (this); - return m_PropagationLoss; + return m_spectrumPropagationLoss; } diff --git a/src/spectrum/model/single-model-spectrum-channel.h b/src/spectrum/model/single-model-spectrum-channel.h index 25be58dc5..a3fb15010 100644 --- a/src/spectrum/model/single-model-spectrum-channel.h +++ b/src/spectrum/model/single-model-spectrum-channel.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +//* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2009 CTTC * @@ -23,8 +23,6 @@ #include -#include -#include namespace ns3 { @@ -47,6 +45,7 @@ public: // inherited from SpectrumChannel + virtual void AddPropagationLossModel (Ptr loss); virtual void AddSpectrumPropagationLossModel (Ptr loss); virtual void SetPropagationDelayModel (Ptr delay); virtual void AddRx (Ptr phy); @@ -97,15 +96,23 @@ private: * propagation delay model to be used with this channel * */ - Ptr m_PropagationDelay; + Ptr m_propagationDelay; /** - * propagation loss model to be used with this channel + * single-frequency propagation loss model to be used with this channel + * + */ + Ptr m_propagationLoss; + + /** + * frequency-dependent propagation loss model to be used with this channel * */ - Ptr m_PropagationLoss; + Ptr m_spectrumPropagationLoss; + + double m_maxLossDb; }; diff --git a/src/spectrum/model/spectrum-channel.h b/src/spectrum/model/spectrum-channel.h index 247f65a26..91850130a 100644 --- a/src/spectrum/model/spectrum-channel.h +++ b/src/spectrum/model/spectrum-channel.h @@ -34,6 +34,7 @@ class PacketBurst; class SpectrumValue; class SpectrumPhy; class SpectrumPropagationLossModel; +class PropagationLossModel; class PropagationDelayModel; /** @@ -50,8 +51,16 @@ public: /** - * set the propagation loss model to be used - * \param loss Ptr to the propagation loss model to be used. + * set the single-frequency propagation loss model to be used + * \warning only models that do not depend on the TX power should be used. + * + * \param loss a pointer to the propagation loss model to be used. + */ + virtual void AddPropagationLossModel (Ptr loss) = 0; + + /** + * set the frequency-dependent propagation loss model to be used + * \param loss a pointer to the propagation loss model to be used. */ virtual void AddSpectrumPropagationLossModel (Ptr loss) = 0; diff --git a/src/spectrum/test/examples-to-run.py b/src/spectrum/test/examples-to-run.py index 2f92d6588..879354120 100644 --- a/src/spectrum/test/examples-to-run.py +++ b/src/spectrum/test/examples-to-run.py @@ -10,6 +10,7 @@ cpp_examples = [ ("adhoc-aloha-ideal-phy", "True", "True"), ("adhoc-aloha-ideal-phy-with-microwave-oven", "True", "True"), + ("adhoc-aloha-ideal-phy-matrix-propagation-loss-model", "True", "True"), ] # A list of Python examples to run in order to ensure that they remain diff --git a/src/spectrum/test/spectrum-ideal-phy-test.cc b/src/spectrum/test/spectrum-ideal-phy-test.cc new file mode 100644 index 000000000..8f01bb838 --- /dev/null +++ b/src/spectrum/test/spectrum-ideal-phy-test.cc @@ -0,0 +1,245 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +NS_LOG_COMPONENT_DEFINE ("SpectrumIdealPhyTest"); + +namespace ns3 { + + +static uint64_t g_rxBytes; +static double g_bandwidth = 20e6; // Hz + +void +PhyRxEndOkTrace (std::string context, Ptr p) +{ + g_rxBytes += p->GetSize (); +} + + +class SpectrumIdealPhyTestCase : public TestCase +{ +public: + SpectrumIdealPhyTestCase (double snrLinear, + uint64_t phyRate, + bool rateIsAchievable, + std::string channelType); + virtual ~SpectrumIdealPhyTestCase (); + +private: + virtual void DoRun (void); + + double m_snrLinear; + uint64_t m_phyRate; + bool m_rateIsAchievable; + std::string m_channelType; +}; + + + + +SpectrumIdealPhyTestCase::SpectrumIdealPhyTestCase (double snrLinear, + uint64_t phyRate, + bool rateIsAchievable, + std::string channelType) + : TestCase (""), + m_snrLinear (snrLinear), + m_phyRate (phyRate), + m_rateIsAchievable (rateIsAchievable), + m_channelType (channelType) +{ + std::ostringstream oss; + oss << channelType + << " snr = " << snrLinear << " (linear), " + << " phyRate = " << phyRate << " bps"; + SetName (oss.str ()); +} + +SpectrumIdealPhyTestCase::~SpectrumIdealPhyTestCase () +{ +} + + +void +SpectrumIdealPhyTestCase::DoRun (void) +{ + NS_LOG_FUNCTION (m_snrLinear << m_phyRate); + double txPowerW = 0.1; + // for the noise, we use the Power Spectral Density of thermal noise + // at room temperature. The value of the PSD will be constant over the band of interest. + const double k = 1.381e-23; //Boltzmann's constant + const double T = 290; // temperature in Kelvin + double noisePsdValue = k * T; // W/Hz + double lossLinear = (txPowerW) / (m_snrLinear * noisePsdValue * g_bandwidth); + double lossDb = 10 * log10 (lossLinear); + uint64_t phyRate = m_phyRate; // bps + uint32_t pktSize = 50; // bytes + + uint32_t numPkts = 200; //desired number of packets in the + //test. Directly related with the accuracy + //of the measurement. + + double testDuration = (numPkts * pktSize * 8.0) / phyRate; + NS_LOG_INFO ("test duration = " << std::fixed << testDuration); + + NodeContainer c; + c.Create (2); + + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector (0.0, 0.0, 0.0)); + positionAlloc->Add (Vector (5.0, 0.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + + + mobility.Install (c); + + + SpectrumChannelHelper channelHelper; + channelHelper.SetChannel (m_channelType); + channelHelper.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel"); + Ptr propLoss = CreateObject (); + propLoss->SetLoss (c.Get(0)->GetObject (), c.Get(1)->GetObject (), lossDb, true); + channelHelper.AddPropagationLoss (propLoss); + Ptr channel = channelHelper.Create (); + + + WifiSpectrumValue5MhzFactory sf; + + uint32_t channelNumber = 1; + Ptr txPsd = sf.CreateTxPowerSpectralDensity (txPowerW, channelNumber); + + Ptr noisePsd = sf.CreateConstant (noisePsdValue); + + AdhocAlohaNoackIdealPhyHelper deviceHelper; + deviceHelper.SetChannel (channel); + deviceHelper.SetTxPowerSpectralDensity (txPsd); + deviceHelper.SetNoisePowerSpectralDensity (noisePsd); + deviceHelper.SetPhyAttribute ("Rate", DataRateValue (DataRate (phyRate))); + NetDeviceContainer devices = deviceHelper.Install (c); + + PacketSocketHelper packetSocket; + packetSocket.Install (c); + + PacketSocketAddress socket; + socket.SetSingleDevice (devices.Get (0)->GetIfIndex ()); + socket.SetPhysicalAddress (devices.Get (1)->GetAddress ()); + socket.SetProtocol (1); + + OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket)); + onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (250))); + onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0))); + onoff.SetAttribute ("DataRate", DataRateValue (DataRate (1.2*phyRate))); + onoff.SetAttribute ("PacketSize", UintegerValue (pktSize)); + + ApplicationContainer apps = onoff.Install (c.Get (0)); + apps.Start (Seconds (0.0)); + apps.Stop (Seconds (testDuration)); + + Config::Connect ("/NodeList/*/DeviceList/*/Phy/RxEndOk", MakeCallback (&PhyRxEndOkTrace)); + + g_rxBytes = 0; + Simulator::Stop (Seconds (testDuration+0.000000001)); + Simulator::Run (); + double throughputBps = (g_rxBytes * 8.0) / testDuration; + + if (m_rateIsAchievable) + { + NS_TEST_ASSERT_MSG_EQ_TOL (throughputBps, m_phyRate, m_phyRate*0.01, "throughput does not match PHY rate"); + } + else + { + NS_TEST_ASSERT_MSG_EQ (throughputBps, 0.0, "PHY rate is not achievable but throughput is non-zero"); + } + + Simulator::Destroy (); +} + + + + +class SpectrumIdealPhyTestSuite : public TestSuite +{ +public: + SpectrumIdealPhyTestSuite (); +}; + +SpectrumIdealPhyTestSuite::SpectrumIdealPhyTestSuite () + : TestSuite ("spectrum-ideal-phy", SYSTEM) +{ + + NS_LOG_INFO ("creating SpectrumIdealPhyTestSuite"); + + for (double snr = 0.01; snr <= 10 ; snr *= 2) + { + double achievableRate = g_bandwidth*log2(1+snr); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.1, true, "ns3::SingleModelSpectrumChannel")); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.5, true, "ns3::SingleModelSpectrumChannel")); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.95, true, "ns3::SingleModelSpectrumChannel")); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*1.05, false, "ns3::SingleModelSpectrumChannel")); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*2, false, "ns3::SingleModelSpectrumChannel")); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*4, false, "ns3::SingleModelSpectrumChannel")); + } + for (double snr = 0.01; snr <= 10 ; snr *= 10) + { + double achievableRate = g_bandwidth*log2(1+snr); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.1, true, "ns3::MultiModelSpectrumChannel")); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.5, true, "ns3::MultiModelSpectrumChannel")); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.95, true, "ns3::MultiModelSpectrumChannel")); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*1.05, false, "ns3::MultiModelSpectrumChannel")); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*2, false, "ns3::MultiModelSpectrumChannel")); + AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*4, false, "ns3::MultiModelSpectrumChannel")); + } +} + +static SpectrumIdealPhyTestSuite g_spectrumIdealPhyTestSuite; + +} // namespace ns3 diff --git a/src/spectrum/wscript b/src/spectrum/wscript index c396aea22..49e205fb7 100644 --- a/src/spectrum/wscript +++ b/src/spectrum/wscript @@ -36,6 +36,7 @@ def build(bld): module_test.source = [ 'test/spectrum-interference-test.cc', 'test/spectrum-value-test.cc', + 'test/spectrum-ideal-phy-test.cc', ] headers = bld.new_task_gen('ns3header')