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