A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
multi-model-spectrum-channel.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 CTTC
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Nicola Baldo <nbaldo@cttc.es>
19  */
20 
21 #include <ns3/object.h>
22 #include <ns3/simulator.h>
23 #include <ns3/log.h>
24 #include <ns3/packet.h>
25 #include <ns3/packet-burst.h>
26 #include <ns3/net-device.h>
27 #include <ns3/node.h>
28 #include <ns3/double.h>
29 #include <ns3/mobility-model.h>
30 #include <ns3/spectrum-phy.h>
31 #include <ns3/spectrum-converter.h>
32 #include <ns3/spectrum-propagation-loss-model.h>
33 #include <ns3/propagation-loss-model.h>
34 #include <ns3/propagation-delay-model.h>
35 #include <ns3/antenna-model.h>
36 #include <ns3/angles.h>
37 #include <iostream>
38 #include <utility>
40 
41 
42 NS_LOG_COMPONENT_DEFINE ("MultiModelSpectrumChannel");
43 
44 
45 namespace ns3 {
46 
47 
48 NS_OBJECT_ENSURE_REGISTERED (MultiModelSpectrumChannel);
49 
50 
51 std::ostream& operator<< (std::ostream& lhs, TxSpectrumModelInfoMap_t& rhs)
52 {
53  for (TxSpectrumModelInfoMap_t::iterator it = rhs.begin ();
54  it != rhs.end ();
55  ++it)
56  {
57  SpectrumConverterMap_t::iterator jt;
58  for (jt = it->second.m_spectrumConverterMap.begin ();
59  jt != it->second.m_spectrumConverterMap.end ();
60  ++jt)
61  {
62  lhs << "(" << it->first << "," << jt->first << ") ";
63  }
64  }
65  return lhs;
66 }
67 
69  : m_txSpectrumModel (txSpectrumModel)
70 {
71 }
72 
73 
75  : m_rxSpectrumModel (rxSpectrumModel)
76 {
77 }
78 
79 
81 {
82  NS_LOG_FUNCTION (this);
83 }
84 
85 void
87 {
88  NS_LOG_FUNCTION (this);
92  m_txSpectrumModelInfoMap.clear ();
93  m_rxSpectrumModelInfoMap.clear ();
95 }
96 
97 TypeId
99 {
100  static TypeId tid = TypeId ("ns3::MultiModelSpectrumChannel")
102  .AddConstructor<MultiModelSpectrumChannel> ()
103  .AddAttribute ("MaxLossDb",
104  "If a single-frequency PropagationLossModel is used, this value "
105  "represents the maximum loss in dB for which transmissions will be "
106  "passed to the receiving PHY. Signals for which the PropagationLossModel "
107  "returns a loss bigger than this value will not be propagated to the receiver. "
108  "This parameter is to be used to reduce "
109  "the computational load by not propagating signals that are far beyond "
110  "the interference range. Note that the default value corresponds to "
111  "considering all signals for reception. Tune this value with care. ",
112  DoubleValue (1.0e9),
113  MakeDoubleAccessor (&MultiModelSpectrumChannel::m_maxLossDb),
114  MakeDoubleChecker<double> ())
115  .AddTraceSource ("PathLoss",
116  "This trace is fired "
117  "whenever a new path loss value is calculated. The first and second parameters "
118  "to the trace are pointers respectively to the TX and RX SpectrumPhy instances, "
119  "whereas the third parameters is the loss value in dB. Note that the loss value "
120  "reported by this trace is the single-frequency loss value obtained by evaluating "
121  "only the TX and RX AntennaModels and the PropagationLossModel. In particular, note that "
122  "SpectrumPropagationLossModel (even if present) is never used to evaluate the loss value "
123  "reported in this trace. ",
125  ;
126  return tid;
127 }
128 
129 
130 
131 void
133 {
134  NS_LOG_FUNCTION (this << phy);
135 
136  Ptr<const SpectrumModel> rxSpectrumModel = phy->GetRxSpectrumModel ();
137 
138  NS_ASSERT_MSG ((0 != rxSpectrumModel), "phy->GetRxSpectrumModel () returned 0. Please check that the RxSpectrumModel is already set for the phy before calling MultiModelSpectrumChannel::AddRx (phy)");
139 
140  SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
141 
142  std::vector<Ptr<SpectrumPhy> >::const_iterator it;
143 
144  // remove a previous entry of this phy if it exists
145  // we need to scan for all rxSpectrumModel values since we don't
146  // know which spectrum model the phy had when it was previously added
147  // (it's probably different than the current one)
148  for (RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
149  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
150  ++rxInfoIterator)
151  {
152  std::set<Ptr<SpectrumPhy> >::iterator phyIt = rxInfoIterator->second.m_rxPhySet.find (phy);
153  if (phyIt != rxInfoIterator->second.m_rxPhySet.end ())
154  {
155  rxInfoIterator->second.m_rxPhySet.erase (phyIt);
156  --m_numDevices;
157  break; // there should be at most one entry
158  }
159  }
160 
161  ++m_numDevices;
162 
163  RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.find (rxSpectrumModelUid);
164 
165  if (rxInfoIterator == m_rxSpectrumModelInfoMap.end ())
166  {
167  // spectrum model unknown, add it to the list of RxSpectrumModels
168  std::pair<RxSpectrumModelInfoMap_t::iterator, bool> ret;
169  ret = m_rxSpectrumModelInfoMap.insert (std::make_pair (rxSpectrumModelUid, RxSpectrumModelInfo (rxSpectrumModel)));
170  NS_ASSERT (ret.second);
171  // also add the phy to the newly created set of SpectrumPhy for this RxSpectrumModel
172  std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = ret.first->second.m_rxPhySet.insert (phy);
173  NS_ASSERT (ret2.second);
174 
175  // and create the necessary converters for all the TX spectrum models that we know of
176  for (TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.begin ();
177  txInfoIterator != m_txSpectrumModelInfoMap.end ();
178  ++txInfoIterator)
179  {
180  Ptr<const SpectrumModel> txSpectrumModel = txInfoIterator->second.m_txSpectrumModel;
181  NS_LOG_LOGIC ("Creating converters between SpectrumModelUids " << txSpectrumModel->GetUid () << " and " << rxSpectrumModelUid );
182  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
183  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
184  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
185  NS_ASSERT (ret2.second);
186  }
187  }
188  else
189  {
190  // spectrum model is already known, just add the device to the corresponding list
191  std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = rxInfoIterator->second.m_rxPhySet.insert (phy);
192  NS_ASSERT (ret2.second);
193  }
194 
195 }
196 
197 
198 TxSpectrumModelInfoMap_t::const_iterator
200 {
201  NS_LOG_FUNCTION (this << txSpectrumModel);
202  SpectrumModelUid_t txSpectrumModelUid = txSpectrumModel->GetUid ();
203  TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.find (txSpectrumModelUid);
204 
205  if (txInfoIterator == m_txSpectrumModelInfoMap.end ())
206  {
207  // first time we see this TX SpectrumModel
208  // we add it to the list
209  std::pair<TxSpectrumModelInfoMap_t::iterator, bool> ret;
210  ret = m_txSpectrumModelInfoMap.insert (std::make_pair (txSpectrumModelUid, TxSpectrumModelInfo (txSpectrumModel)));
211  NS_ASSERT (ret.second);
212  txInfoIterator = ret.first;
213 
214  // and we create the converters for all the RX SpectrumModels that we know of
215  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
216  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
217  ++rxInfoIterator)
218  {
219  Ptr<const SpectrumModel> rxSpectrumModel = rxInfoIterator->second.m_rxSpectrumModel;
220  SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
221 
222  if (rxSpectrumModelUid != txSpectrumModelUid)
223  {
224  NS_LOG_LOGIC ("Creating converters between SpectrumModelUids " << txSpectrumModelUid << " and " << rxSpectrumModelUid );
225 
226  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
227  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
228  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
229  NS_ASSERT (ret2.second);
230  }
231  }
232  }
233  else
234  {
235  NS_LOG_LOGIC ("SpectrumModelUid " << txSpectrumModelUid << " already present");
236  }
237  return txInfoIterator;
238 }
239 
240 
241 
242 void
244 {
245  NS_LOG_FUNCTION (this << txParams);
246 
247  NS_ASSERT (txParams->txPhy);
248  NS_ASSERT (txParams->psd);
249 
250 
251  Ptr<MobilityModel> txMobility = txParams->txPhy->GetMobility ();
252  SpectrumModelUid_t txSpectrumModelUid = txParams->psd->GetSpectrumModelUid ();
253  NS_LOG_LOGIC (" txSpectrumModelUid " << txSpectrumModelUid);
254 
255  //
256  TxSpectrumModelInfoMap_t::const_iterator txInfoIteratorerator = FindAndEventuallyAddTxSpectrumModel (txParams->psd->GetSpectrumModel ());
257  NS_ASSERT (txInfoIteratorerator != m_txSpectrumModelInfoMap.end ());
258 
259  NS_LOG_LOGIC ("converter map for TX SpectrumModel with Uid " << txInfoIteratorerator->first);
260  NS_LOG_LOGIC ("converter map size: " << txInfoIteratorerator->second.m_spectrumConverterMap.size ());
261  NS_LOG_LOGIC ("converter map first element: " << txInfoIteratorerator->second.m_spectrumConverterMap.begin ()->first);
262 
263  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
264  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
265  ++rxInfoIterator)
266  {
267  SpectrumModelUid_t rxSpectrumModelUid = rxInfoIterator->second.m_rxSpectrumModel->GetUid ();
268  NS_LOG_LOGIC (" rxSpectrumModelUids " << rxSpectrumModelUid);
269 
270  Ptr <SpectrumValue> convertedTxPowerSpectrum;
271  if (txSpectrumModelUid == rxSpectrumModelUid)
272  {
273  NS_LOG_LOGIC ("no spectrum conversion needed");
274  convertedTxPowerSpectrum = txParams->psd;
275  }
276  else
277  {
278  NS_LOG_LOGIC (" converting txPowerSpectrum SpectrumModelUids" << txSpectrumModelUid << " --> " << rxSpectrumModelUid);
279  SpectrumConverterMap_t::const_iterator rxConverterIterator = txInfoIteratorerator->second.m_spectrumConverterMap.find (rxSpectrumModelUid);
280  NS_ASSERT (rxConverterIterator != txInfoIteratorerator->second.m_spectrumConverterMap.end ());
281  convertedTxPowerSpectrum = rxConverterIterator->second.Convert (txParams->psd);
282  }
283 
284 
285  for (std::set<Ptr<SpectrumPhy> >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhySet.begin ();
286  rxPhyIterator != rxInfoIterator->second.m_rxPhySet.end ();
287  ++rxPhyIterator)
288  {
289  NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid,
290  "SpectrumModel change was not notified to MultiModelSpectrumChannel (i.e., AddRx should be called again after model is changed)");
291 
292  if ((*rxPhyIterator) != txParams->txPhy)
293  {
294  NS_LOG_LOGIC (" copying signal parameters " << txParams);
295  Ptr<SpectrumSignalParameters> rxParams = txParams->Copy ();
296  rxParams->psd = Copy<SpectrumValue> (convertedTxPowerSpectrum);
297  Time delay = MicroSeconds (0);
298 
299  Ptr<MobilityModel> receiverMobility = (*rxPhyIterator)->GetMobility ();
300 
301  if (txMobility && receiverMobility)
302  {
303  double pathLossDb = 0;
304  if (rxParams->txAntenna != 0)
305  {
306  Angles txAngles (receiverMobility->GetPosition (), txMobility->GetPosition ());
307  double txAntennaGain = rxParams->txAntenna->GetGainDb (txAngles);
308  NS_LOG_LOGIC ("txAntennaGain = " << txAntennaGain << " dB");
309  pathLossDb -= txAntennaGain;
310  }
311  Ptr<AntennaModel> rxAntenna = (*rxPhyIterator)->GetRxAntenna ();
312  if (rxAntenna != 0)
313  {
314  Angles rxAngles (txMobility->GetPosition (), receiverMobility->GetPosition ());
315  double rxAntennaGain = rxAntenna->GetGainDb (rxAngles);
316  NS_LOG_LOGIC ("rxAntennaGain = " << rxAntennaGain << " dB");
317  pathLossDb -= rxAntennaGain;
318  }
319  if (m_propagationLoss)
320  {
321  double propagationGainDb = m_propagationLoss->CalcRxPower (0, txMobility, receiverMobility);
322  NS_LOG_LOGIC ("propagationGainDb = " << propagationGainDb << " dB");
323  pathLossDb -= propagationGainDb;
324  }
325  NS_LOG_LOGIC ("total pathLoss = " << pathLossDb << " dB");
326  m_pathLossTrace (txParams->txPhy, *rxPhyIterator, pathLossDb);
327  if ( pathLossDb > m_maxLossDb)
328  {
329  // beyond range
330  continue;
331  }
332  double pathGainLinear = std::pow (10.0, (-pathLossDb) / 10.0);
333  *(rxParams->psd) *= pathGainLinear;
334 
336  {
337  rxParams->psd = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity (rxParams->psd, txMobility, receiverMobility);
338  }
339 
340  if (m_propagationDelay)
341  {
342  delay = m_propagationDelay->GetDelay (txMobility, receiverMobility);
343  }
344  }
345 
346  Ptr<NetDevice> netDev = (*rxPhyIterator)->GetDevice ();
347  if (netDev)
348  {
349  // the receiver has a NetDevice, so we expect that it is attached to a Node
350  uint32_t dstNode = netDev->GetNode ()->GetId ();
352  rxParams, *rxPhyIterator);
353  }
354  else
355  {
356  // the receiver is not attached to a NetDevice, so we cannot assume that it is attached to a node
358  rxParams, *rxPhyIterator);
359  }
360  }
361  }
362 
363  }
364 
365 }
366 
367 void
369 {
370  NS_LOG_FUNCTION (this);
371  receiver->StartRx (params);
372 }
373 
374 
375 
376 uint32_t
378 {
379  return m_numDevices;
380 
381 }
382 
383 
386 {
387  NS_ASSERT (i < m_numDevices);
388  // this method implementation is computationally intensive. This
389  // method would be faster if we actually used a std::vector for
390  // storing devices, which we don't due to the need to have fast
391  // SpectrumModel conversions and to allow PHY devices to changea
392  // SpectrumModel at run time. Note that having this method slow is
393  // acceptable as it is not used much at run time (often not at all).
394  // On the other hand, having slow SpectrumModel conversion would be
395  // less acceptable.
396  uint32_t j = 0;
397  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
398  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
399  ++rxInfoIterator)
400  {
401  for (std::set<Ptr<SpectrumPhy> >::const_iterator phyIt = rxInfoIterator->second.m_rxPhySet.begin ();
402  phyIt != rxInfoIterator->second.m_rxPhySet.end ();
403  ++phyIt)
404  {
405  if (j == i)
406  {
407  return (*phyIt)->GetDevice ();
408  }
409  }
410  }
411  NS_FATAL_ERROR ("m_numDevice > actual number of devices");
412  return 0;
413 }
414 
415 
416 
417 void
419 {
420  NS_LOG_FUNCTION (this << loss);
422  m_propagationLoss = loss;
423 }
424 
425 void
427 {
430 }
431 
432 void
434 {
436  m_propagationDelay = delay;
437 }
438 
441 {
442  NS_LOG_FUNCTION (this);
444 }
445 
446 
447 } // namespace ns3
Ptr< SpectrumPropagationLossModel > m_spectrumPropagationLoss
frequency-dependent propagation loss model to be used with this channel
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint32_t SpectrumModelUid_t
virtual void StartRx(Ptr< SpectrumSignalParameters > params)=0
Notify the SpectrumPhy instance of an incoming signal.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
virtual void AddPropagationLossModel(Ptr< PropagationLossModel > loss)
set the single-frequency propagation loss model to be used
Vector GetPosition(void) const
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: object.cc:335
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
RxSpectrumModelInfoMap_t m_rxSpectrumModelInfoMap
data structure holding, for each RX spectrum model, all the corresponding SpectrumPhy instances...
virtual Ptr< const SpectrumModel > GetRxSpectrumModel() const =0
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:825
virtual Ptr< SpectrumPropagationLossModel > GetSpectrumPropagationLossModel(void)
Ptr< PropagationDelayModel > m_propagationDelay
propagation delay model to be used with this channel
Ptr< PropagationLossModel > m_propagationLoss
single-frequency propagation loss model to be used with this channel
Class which implements a converter between SpectrumValue which are defined over different SpectrumMod...
virtual uint32_t GetNDevices(void) const
SpectrumModelUid_t GetUid() const
virtual void AddRx(Ptr< SpectrumPhy > phy)
add a SpectrumPhy to a channel, so it can receive packets
TxSpectrumModelInfoMap_t::const_iterator FindAndEventuallyAddTxSpectrumModel(Ptr< const SpectrumModel > txSpectrumModel)
this method checks if m_rxSpectrumModelInfoMap contains an entry for the given TX SpectrumModel...
double CalcRxPower(double txPowerDbm, Ptr< MobilityModel > a, Ptr< MobilityModel > b) const
static void ScheduleWithContext(uint32_t context, Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event with the given context.
Definition: simulator.h:905
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:233
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:43
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
RxSpectrumModelInfo(Ptr< const SpectrumModel > rxSpectrumModel)
void DoDispose()
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
virtual void AddSpectrumPropagationLossModel(Ptr< SpectrumPropagationLossModel > loss)
set the frequency-dependent propagation loss model to be used
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:84
TracedCallback< Ptr< SpectrumPhy >, Ptr< SpectrumPhy >, double > m_pathLossTrace
virtual void StartTx(Ptr< SpectrumSignalParameters > params)
Used by attached PHY instances to transmit signals on the channel.
std::map< SpectrumModelUid_t, TxSpectrumModelInfo > TxSpectrumModelInfoMap_t
virtual Ptr< NetDevice > GetDevice(uint32_t i) const
virtual void SetPropagationDelayModel(Ptr< PropagationDelayModel > delay)
set the propagation delay model to be used
TxSpectrumModelInfoMap_t m_txSpectrumModelInfoMap
data structure holding, for each TX SpectrumModel, all the converters to any RX SpectrumModel, and all the corresponding SpectrumPhy instances.
Defines the interface for spectrum-aware channel implementations.
struct holding the azimuth and inclination angles of spherical coordinates.
Definition: angles.h:71
TxSpectrumModelInfo(Ptr< const SpectrumModel > txSpectrumModel)
Hold a floating point type.
Definition: double.h:41
a unique identifier for an interface.
Definition: type-id.h:49
virtual void StartRx(Ptr< SpectrumSignalParameters > params, Ptr< SpectrumPhy > receiver)
used internally to reschedule transmission after the propagation delay
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610