A Discrete-Event Network Simulator
API
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 namespace ns3 {
43 
44 NS_LOG_COMPONENT_DEFINE ("MultiModelSpectrumChannel");
45 
46 NS_OBJECT_ENSURE_REGISTERED (MultiModelSpectrumChannel);
47 
48 
49 std::ostream& operator<< (std::ostream& lhs, TxSpectrumModelInfoMap_t& rhs)
50 {
51  for (TxSpectrumModelInfoMap_t::iterator it = rhs.begin ();
52  it != rhs.end ();
53  ++it)
54  {
55  SpectrumConverterMap_t::iterator jt;
56  for (jt = it->second.m_spectrumConverterMap.begin ();
57  jt != it->second.m_spectrumConverterMap.end ();
58  ++jt)
59  {
60  lhs << "(" << it->first << "," << jt->first << ") ";
61  }
62  }
63  return lhs;
64 }
65 
67  : m_txSpectrumModel (txSpectrumModel)
68 {
69 }
70 
71 
73  : m_rxSpectrumModel (rxSpectrumModel)
74 {
75 }
76 
77 
79 {
80  NS_LOG_FUNCTION (this);
81 }
82 
83 void
85 {
86  NS_LOG_FUNCTION (this);
90  m_txSpectrumModelInfoMap.clear ();
91  m_rxSpectrumModelInfoMap.clear ();
93 }
94 
95 TypeId
97 {
98  static TypeId tid = TypeId ("ns3::MultiModelSpectrumChannel")
100  .SetGroupName ("Spectrum")
101  .AddConstructor<MultiModelSpectrumChannel> ()
102  .AddAttribute ("MaxLossDb",
103  "If a single-frequency PropagationLossModel is used, "
104  "this value represents the maximum loss in dB for which "
105  "transmissions will be passed to the receiving PHY. "
106  "Signals for which the PropagationLossModel returns "
107  "a loss bigger than this value will not be propagated "
108  "to the receiver. This parameter is to be used to reduce "
109  "the computational load by not propagating signals that "
110  "are far beyond the interference range. Note that the "
111  "default value corresponds to considering all signals "
112  "for reception. Tune this value with care. ",
113  DoubleValue (1.0e9),
115  MakeDoubleChecker<double> ())
116  .AddTraceSource ("PathLoss",
117  "This trace is fired whenever a new path loss value "
118  "is calculated. The first and second parameters "
119  "to the trace are pointers respectively to the "
120  "TX and RX SpectrumPhy instances, whereas the "
121  "third parameters is the loss value in dB. "
122  "Note that the loss value reported by this trace is "
123  "the single-frequency loss value obtained by evaluating "
124  "only the TX and RX AntennaModels and the "
125  "PropagationLossModel. In particular, note that "
126  "SpectrumPropagationLossModel (even if present) "
127  "is never used to evaluate the loss value "
128  "reported in this trace. ",
130  "ns3::SpectrumChannel::LossTracedCallback")
131  ;
132  return tid;
133 }
134 
135 
136 
137 void
139 {
140  NS_LOG_FUNCTION (this << phy);
141 
142  Ptr<const SpectrumModel> rxSpectrumModel = phy->GetRxSpectrumModel ();
143 
144  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)");
145 
146  SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
147 
148  std::vector<Ptr<SpectrumPhy> >::const_iterator it;
149 
150  // remove a previous entry of this phy if it exists
151  // we need to scan for all rxSpectrumModel values since we don't
152  // know which spectrum model the phy had when it was previously added
153  // (it's probably different than the current one)
154  for (RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
155  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
156  ++rxInfoIterator)
157  {
158  std::set<Ptr<SpectrumPhy> >::iterator phyIt = rxInfoIterator->second.m_rxPhySet.find (phy);
159  if (phyIt != rxInfoIterator->second.m_rxPhySet.end ())
160  {
161  rxInfoIterator->second.m_rxPhySet.erase (phyIt);
162  --m_numDevices;
163  break; // there should be at most one entry
164  }
165  }
166 
167  ++m_numDevices;
168 
169  RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.find (rxSpectrumModelUid);
170 
171  if (rxInfoIterator == m_rxSpectrumModelInfoMap.end ())
172  {
173  // spectrum model unknown, add it to the list of RxSpectrumModels
174  std::pair<RxSpectrumModelInfoMap_t::iterator, bool> ret;
175  ret = m_rxSpectrumModelInfoMap.insert (std::make_pair (rxSpectrumModelUid, RxSpectrumModelInfo (rxSpectrumModel)));
176  NS_ASSERT (ret.second);
177  // also add the phy to the newly created set of SpectrumPhy for this RxSpectrumModel
178  std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = ret.first->second.m_rxPhySet.insert (phy);
179  NS_ASSERT (ret2.second);
180 
181  // and create the necessary converters for all the TX spectrum models that we know of
182  for (TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.begin ();
183  txInfoIterator != m_txSpectrumModelInfoMap.end ();
184  ++txInfoIterator)
185  {
186  Ptr<const SpectrumModel> txSpectrumModel = txInfoIterator->second.m_txSpectrumModel;
187  NS_LOG_LOGIC ("Creating converters between SpectrumModelUids " << txSpectrumModel->GetUid () << " and " << rxSpectrumModelUid );
188  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
189  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
190  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
191  NS_ASSERT (ret2.second);
192  }
193  }
194  else
195  {
196  // spectrum model is already known, just add the device to the corresponding list
197  std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = rxInfoIterator->second.m_rxPhySet.insert (phy);
198  NS_ASSERT (ret2.second);
199  }
200 
201 }
202 
203 
204 TxSpectrumModelInfoMap_t::const_iterator
206 {
207  NS_LOG_FUNCTION (this << txSpectrumModel);
208  SpectrumModelUid_t txSpectrumModelUid = txSpectrumModel->GetUid ();
209  TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.find (txSpectrumModelUid);
210 
211  if (txInfoIterator == m_txSpectrumModelInfoMap.end ())
212  {
213  // first time we see this TX SpectrumModel
214  // we add it to the list
215  std::pair<TxSpectrumModelInfoMap_t::iterator, bool> ret;
216  ret = m_txSpectrumModelInfoMap.insert (std::make_pair (txSpectrumModelUid, TxSpectrumModelInfo (txSpectrumModel)));
217  NS_ASSERT (ret.second);
218  txInfoIterator = ret.first;
219 
220  // and we create the converters for all the RX SpectrumModels that we know of
221  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
222  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
223  ++rxInfoIterator)
224  {
225  Ptr<const SpectrumModel> rxSpectrumModel = rxInfoIterator->second.m_rxSpectrumModel;
226  SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
227 
228  if (rxSpectrumModelUid != txSpectrumModelUid)
229  {
230  NS_LOG_LOGIC ("Creating converters between SpectrumModelUids " << txSpectrumModelUid << " and " << rxSpectrumModelUid );
231 
232  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
233  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
234  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
235  NS_ASSERT (ret2.second);
236  }
237  }
238  }
239  else
240  {
241  NS_LOG_LOGIC ("SpectrumModelUid " << txSpectrumModelUid << " already present");
242  }
243  return txInfoIterator;
244 }
245 
246 
247 
248 void
250 {
251  NS_LOG_FUNCTION (this << txParams);
252 
253  NS_ASSERT (txParams->txPhy);
254  NS_ASSERT (txParams->psd);
255 
256 
257  Ptr<MobilityModel> txMobility = txParams->txPhy->GetMobility ();
258  SpectrumModelUid_t txSpectrumModelUid = txParams->psd->GetSpectrumModelUid ();
259  NS_LOG_LOGIC (" txSpectrumModelUid " << txSpectrumModelUid);
260 
261  //
262  TxSpectrumModelInfoMap_t::const_iterator txInfoIteratorerator = FindAndEventuallyAddTxSpectrumModel (txParams->psd->GetSpectrumModel ());
263  NS_ASSERT (txInfoIteratorerator != m_txSpectrumModelInfoMap.end ());
264 
265  NS_LOG_LOGIC ("converter map for TX SpectrumModel with Uid " << txInfoIteratorerator->first);
266  NS_LOG_LOGIC ("converter map size: " << txInfoIteratorerator->second.m_spectrumConverterMap.size ());
267  NS_LOG_LOGIC ("converter map first element: " << txInfoIteratorerator->second.m_spectrumConverterMap.begin ()->first);
268 
269  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
270  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
271  ++rxInfoIterator)
272  {
273  SpectrumModelUid_t rxSpectrumModelUid = rxInfoIterator->second.m_rxSpectrumModel->GetUid ();
274  NS_LOG_LOGIC (" rxSpectrumModelUids " << rxSpectrumModelUid);
275 
276  Ptr <SpectrumValue> convertedTxPowerSpectrum;
277  if (txSpectrumModelUid == rxSpectrumModelUid)
278  {
279  NS_LOG_LOGIC ("no spectrum conversion needed");
280  convertedTxPowerSpectrum = txParams->psd;
281  }
282  else
283  {
284  NS_LOG_LOGIC (" converting txPowerSpectrum SpectrumModelUids" << txSpectrumModelUid << " --> " << rxSpectrumModelUid);
285  SpectrumConverterMap_t::const_iterator rxConverterIterator = txInfoIteratorerator->second.m_spectrumConverterMap.find (rxSpectrumModelUid);
286  NS_ASSERT (rxConverterIterator != txInfoIteratorerator->second.m_spectrumConverterMap.end ());
287  convertedTxPowerSpectrum = rxConverterIterator->second.Convert (txParams->psd);
288  }
289 
290 
291  for (std::set<Ptr<SpectrumPhy> >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhySet.begin ();
292  rxPhyIterator != rxInfoIterator->second.m_rxPhySet.end ();
293  ++rxPhyIterator)
294  {
295  NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid,
296  "SpectrumModel change was not notified to MultiModelSpectrumChannel (i.e., AddRx should be called again after model is changed)");
297 
298  if ((*rxPhyIterator) != txParams->txPhy)
299  {
300  NS_LOG_LOGIC (" copying signal parameters " << txParams);
301  Ptr<SpectrumSignalParameters> rxParams = txParams->Copy ();
302  rxParams->psd = Copy<SpectrumValue> (convertedTxPowerSpectrum);
303  Time delay = MicroSeconds (0);
304 
305  Ptr<MobilityModel> receiverMobility = (*rxPhyIterator)->GetMobility ();
306 
307  if (txMobility && receiverMobility)
308  {
309  double pathLossDb = 0;
310  if (rxParams->txAntenna != 0)
311  {
312  Angles txAngles (receiverMobility->GetPosition (), txMobility->GetPosition ());
313  double txAntennaGain = rxParams->txAntenna->GetGainDb (txAngles);
314  NS_LOG_LOGIC ("txAntennaGain = " << txAntennaGain << " dB");
315  pathLossDb -= txAntennaGain;
316  }
317  Ptr<AntennaModel> rxAntenna = (*rxPhyIterator)->GetRxAntenna ();
318  if (rxAntenna != 0)
319  {
320  Angles rxAngles (txMobility->GetPosition (), receiverMobility->GetPosition ());
321  double rxAntennaGain = rxAntenna->GetGainDb (rxAngles);
322  NS_LOG_LOGIC ("rxAntennaGain = " << rxAntennaGain << " dB");
323  pathLossDb -= rxAntennaGain;
324  }
325  if (m_propagationLoss)
326  {
327  double propagationGainDb = m_propagationLoss->CalcRxPower (0, txMobility, receiverMobility);
328  NS_LOG_LOGIC ("propagationGainDb = " << propagationGainDb << " dB");
329  pathLossDb -= propagationGainDb;
330  }
331  NS_LOG_LOGIC ("total pathLoss = " << pathLossDb << " dB");
332  m_pathLossTrace (txParams->txPhy, *rxPhyIterator, pathLossDb);
333  if ( pathLossDb > m_maxLossDb)
334  {
335  // beyond range
336  continue;
337  }
338  double pathGainLinear = std::pow (10.0, (-pathLossDb) / 10.0);
339  *(rxParams->psd) *= pathGainLinear;
340 
342  {
343  rxParams->psd = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity (rxParams->psd, txMobility, receiverMobility);
344  }
345 
346  if (m_propagationDelay)
347  {
348  delay = m_propagationDelay->GetDelay (txMobility, receiverMobility);
349  }
350  }
351 
352  Ptr<NetDevice> netDev = (*rxPhyIterator)->GetDevice ();
353  if (netDev)
354  {
355  // the receiver has a NetDevice, so we expect that it is attached to a Node
356  uint32_t dstNode = netDev->GetNode ()->GetId ();
358  rxParams, *rxPhyIterator);
359  }
360  else
361  {
362  // the receiver is not attached to a NetDevice, so we cannot assume that it is attached to a node
364  rxParams, *rxPhyIterator);
365  }
366  }
367  }
368 
369  }
370 
371 }
372 
373 void
375 {
376  NS_LOG_FUNCTION (this);
377  receiver->StartRx (params);
378 }
379 
380 
381 
382 uint32_t
384 {
385  return m_numDevices;
386 
387 }
388 
389 
392 {
393  NS_ASSERT (i < m_numDevices);
394  // this method implementation is computationally intensive. This
395  // method would be faster if we actually used a std::vector for
396  // storing devices, which we don't due to the need to have fast
397  // SpectrumModel conversions and to allow PHY devices to changea
398  // SpectrumModel at run time. Note that having this method slow is
399  // acceptable as it is not used much at run time (often not at all).
400  // On the other hand, having slow SpectrumModel conversion would be
401  // less acceptable.
402  uint32_t j = 0;
403  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
404  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
405  ++rxInfoIterator)
406  {
407  for (std::set<Ptr<SpectrumPhy> >::const_iterator phyIt = rxInfoIterator->second.m_rxPhySet.begin ();
408  phyIt != rxInfoIterator->second.m_rxPhySet.end ();
409  ++phyIt)
410  {
411  if (j == i)
412  {
413  return (*phyIt)->GetDevice ();
414  }
415  j++;
416  }
417  }
418  NS_FATAL_ERROR ("m_numDevice > actual number of devices");
419  return 0;
420 }
421 
422 
423 
424 void
426 {
427  NS_LOG_FUNCTION (this << loss);
429  m_propagationLoss = loss;
430 }
431 
432 void
434 {
437 }
438 
439 void
441 {
443  m_propagationDelay = delay;
444 }
445 
448 {
449  NS_LOG_FUNCTION (this);
451 }
452 
453 
454 } // 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:102
#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 an Object subclass with the TypeId system.
Definition: object-base.h:44
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
virtual void AddPropagationLossModel(Ptr< PropagationLossModel > loss)
set the single-frequency propagation loss model to be used
Vector GetPosition(void) const
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:339
#define NS_FATAL_ERROR(msg)
Fatal error handling.
Definition: fatal-error.h:100
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:819
This SpectrumChannel implementation can handle the presence of SpectrumPhy instances which can use di...
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
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
Returns the Rx Power taking into account all the PropagatinLossModel(s) chained to the current one...
static void ScheduleWithContext(uint32_t context, Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event with the given context.
Definition: simulator.h:899
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:42
Every class exported by the ns3 library is enclosed in the ns3 namespace.
RxSpectrumModelInfo(Ptr< const SpectrumModel > rxSpectrumModel)
void DoDispose()
Destructor implementation.
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:90
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: double.h:42
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.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:882
struct holding the azimuth and inclination angles of spherical coordinates.
Definition: angles.h:71
TxSpectrumModelInfo(Ptr< const SpectrumModel > txSpectrumModel)
This class can be used to hold variables of floating point type such as 'double' or 'float'...
Definition: double.h:41
a unique identifier for an interface.
Definition: type-id.h:57
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:638