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  .AddConstructor<MultiModelSpectrumChannel> ()
101  .AddAttribute ("MaxLossDb",
102  "If a single-frequency PropagationLossModel is used, "
103  "this value represents the maximum loss in dB for which "
104  "transmissions will be passed to the receiving PHY. "
105  "Signals for which the PropagationLossModel returns "
106  "a loss bigger than this value will not be propagated "
107  "to the receiver. This parameter is to be used to reduce "
108  "the computational load by not propagating signals that "
109  "are far beyond the interference range. Note that the "
110  "default value corresponds to considering all signals "
111  "for reception. Tune this value with care. ",
112  DoubleValue (1.0e9),
114  MakeDoubleChecker<double> ())
115  .AddTraceSource ("PathLoss",
116  "This trace is fired whenever a new path loss value "
117  "is calculated. The first and second parameters "
118  "to the trace are pointers respectively to the "
119  "TX and RX SpectrumPhy instances, whereas the "
120  "third parameters is the loss value in dB. "
121  "Note that the loss value reported by this trace is "
122  "the single-frequency loss value obtained by evaluating "
123  "only the TX and RX AntennaModels and the "
124  "PropagationLossModel. In particular, note that "
125  "SpectrumPropagationLossModel (even if present) "
126  "is never used to evaluate the loss value "
127  "reported in this trace. ",
129  "ns3::SpectrumChannel::LossTracedCallback")
130  ;
131  return tid;
132 }
133 
134 
135 
136 void
138 {
139  NS_LOG_FUNCTION (this << phy);
140 
141  Ptr<const SpectrumModel> rxSpectrumModel = phy->GetRxSpectrumModel ();
142 
143  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)");
144 
145  SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
146 
147  std::vector<Ptr<SpectrumPhy> >::const_iterator it;
148 
149  // remove a previous entry of this phy if it exists
150  // we need to scan for all rxSpectrumModel values since we don't
151  // know which spectrum model the phy had when it was previously added
152  // (it's probably different than the current one)
153  for (RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
154  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
155  ++rxInfoIterator)
156  {
157  std::set<Ptr<SpectrumPhy> >::iterator phyIt = rxInfoIterator->second.m_rxPhySet.find (phy);
158  if (phyIt != rxInfoIterator->second.m_rxPhySet.end ())
159  {
160  rxInfoIterator->second.m_rxPhySet.erase (phyIt);
161  --m_numDevices;
162  break; // there should be at most one entry
163  }
164  }
165 
166  ++m_numDevices;
167 
168  RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.find (rxSpectrumModelUid);
169 
170  if (rxInfoIterator == m_rxSpectrumModelInfoMap.end ())
171  {
172  // spectrum model unknown, add it to the list of RxSpectrumModels
173  std::pair<RxSpectrumModelInfoMap_t::iterator, bool> ret;
174  ret = m_rxSpectrumModelInfoMap.insert (std::make_pair (rxSpectrumModelUid, RxSpectrumModelInfo (rxSpectrumModel)));
175  NS_ASSERT (ret.second);
176  // also add the phy to the newly created set of SpectrumPhy for this RxSpectrumModel
177  std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = ret.first->second.m_rxPhySet.insert (phy);
178  NS_ASSERT (ret2.second);
179 
180  // and create the necessary converters for all the TX spectrum models that we know of
181  for (TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.begin ();
182  txInfoIterator != m_txSpectrumModelInfoMap.end ();
183  ++txInfoIterator)
184  {
185  Ptr<const SpectrumModel> txSpectrumModel = txInfoIterator->second.m_txSpectrumModel;
186  NS_LOG_LOGIC ("Creating converters between SpectrumModelUids " << txSpectrumModel->GetUid () << " and " << rxSpectrumModelUid );
187  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
188  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
189  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
190  NS_ASSERT (ret2.second);
191  }
192  }
193  else
194  {
195  // spectrum model is already known, just add the device to the corresponding list
196  std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = rxInfoIterator->second.m_rxPhySet.insert (phy);
197  NS_ASSERT (ret2.second);
198  }
199 
200 }
201 
202 
203 TxSpectrumModelInfoMap_t::const_iterator
205 {
206  NS_LOG_FUNCTION (this << txSpectrumModel);
207  SpectrumModelUid_t txSpectrumModelUid = txSpectrumModel->GetUid ();
208  TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.find (txSpectrumModelUid);
209 
210  if (txInfoIterator == m_txSpectrumModelInfoMap.end ())
211  {
212  // first time we see this TX SpectrumModel
213  // we add it to the list
214  std::pair<TxSpectrumModelInfoMap_t::iterator, bool> ret;
215  ret = m_txSpectrumModelInfoMap.insert (std::make_pair (txSpectrumModelUid, TxSpectrumModelInfo (txSpectrumModel)));
216  NS_ASSERT (ret.second);
217  txInfoIterator = ret.first;
218 
219  // and we create the converters for all the RX SpectrumModels that we know of
220  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
221  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
222  ++rxInfoIterator)
223  {
224  Ptr<const SpectrumModel> rxSpectrumModel = rxInfoIterator->second.m_rxSpectrumModel;
225  SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
226 
227  if (rxSpectrumModelUid != txSpectrumModelUid)
228  {
229  NS_LOG_LOGIC ("Creating converters between SpectrumModelUids " << txSpectrumModelUid << " and " << rxSpectrumModelUid );
230 
231  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
232  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
233  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
234  NS_ASSERT (ret2.second);
235  }
236  }
237  }
238  else
239  {
240  NS_LOG_LOGIC ("SpectrumModelUid " << txSpectrumModelUid << " already present");
241  }
242  return txInfoIterator;
243 }
244 
245 
246 
247 void
249 {
250  NS_LOG_FUNCTION (this << txParams);
251 
252  NS_ASSERT (txParams->txPhy);
253  NS_ASSERT (txParams->psd);
254 
255 
256  Ptr<MobilityModel> txMobility = txParams->txPhy->GetMobility ();
257  SpectrumModelUid_t txSpectrumModelUid = txParams->psd->GetSpectrumModelUid ();
258  NS_LOG_LOGIC (" txSpectrumModelUid " << txSpectrumModelUid);
259 
260  //
261  TxSpectrumModelInfoMap_t::const_iterator txInfoIteratorerator = FindAndEventuallyAddTxSpectrumModel (txParams->psd->GetSpectrumModel ());
262  NS_ASSERT (txInfoIteratorerator != m_txSpectrumModelInfoMap.end ());
263 
264  NS_LOG_LOGIC ("converter map for TX SpectrumModel with Uid " << txInfoIteratorerator->first);
265  NS_LOG_LOGIC ("converter map size: " << txInfoIteratorerator->second.m_spectrumConverterMap.size ());
266  NS_LOG_LOGIC ("converter map first element: " << txInfoIteratorerator->second.m_spectrumConverterMap.begin ()->first);
267 
268  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
269  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
270  ++rxInfoIterator)
271  {
272  SpectrumModelUid_t rxSpectrumModelUid = rxInfoIterator->second.m_rxSpectrumModel->GetUid ();
273  NS_LOG_LOGIC (" rxSpectrumModelUids " << rxSpectrumModelUid);
274 
275  Ptr <SpectrumValue> convertedTxPowerSpectrum;
276  if (txSpectrumModelUid == rxSpectrumModelUid)
277  {
278  NS_LOG_LOGIC ("no spectrum conversion needed");
279  convertedTxPowerSpectrum = txParams->psd;
280  }
281  else
282  {
283  NS_LOG_LOGIC (" converting txPowerSpectrum SpectrumModelUids" << txSpectrumModelUid << " --> " << rxSpectrumModelUid);
284  SpectrumConverterMap_t::const_iterator rxConverterIterator = txInfoIteratorerator->second.m_spectrumConverterMap.find (rxSpectrumModelUid);
285  NS_ASSERT (rxConverterIterator != txInfoIteratorerator->second.m_spectrumConverterMap.end ());
286  convertedTxPowerSpectrum = rxConverterIterator->second.Convert (txParams->psd);
287  }
288 
289 
290  for (std::set<Ptr<SpectrumPhy> >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhySet.begin ();
291  rxPhyIterator != rxInfoIterator->second.m_rxPhySet.end ();
292  ++rxPhyIterator)
293  {
294  NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid,
295  "SpectrumModel change was not notified to MultiModelSpectrumChannel (i.e., AddRx should be called again after model is changed)");
296 
297  if ((*rxPhyIterator) != txParams->txPhy)
298  {
299  NS_LOG_LOGIC (" copying signal parameters " << txParams);
300  Ptr<SpectrumSignalParameters> rxParams = txParams->Copy ();
301  rxParams->psd = Copy<SpectrumValue> (convertedTxPowerSpectrum);
302  Time delay = MicroSeconds (0);
303 
304  Ptr<MobilityModel> receiverMobility = (*rxPhyIterator)->GetMobility ();
305 
306  if (txMobility && receiverMobility)
307  {
308  double pathLossDb = 0;
309  if (rxParams->txAntenna != 0)
310  {
311  Angles txAngles (receiverMobility->GetPosition (), txMobility->GetPosition ());
312  double txAntennaGain = rxParams->txAntenna->GetGainDb (txAngles);
313  NS_LOG_LOGIC ("txAntennaGain = " << txAntennaGain << " dB");
314  pathLossDb -= txAntennaGain;
315  }
316  Ptr<AntennaModel> rxAntenna = (*rxPhyIterator)->GetRxAntenna ();
317  if (rxAntenna != 0)
318  {
319  Angles rxAngles (txMobility->GetPosition (), receiverMobility->GetPosition ());
320  double rxAntennaGain = rxAntenna->GetGainDb (rxAngles);
321  NS_LOG_LOGIC ("rxAntennaGain = " << rxAntennaGain << " dB");
322  pathLossDb -= rxAntennaGain;
323  }
324  if (m_propagationLoss)
325  {
326  double propagationGainDb = m_propagationLoss->CalcRxPower (0, txMobility, receiverMobility);
327  NS_LOG_LOGIC ("propagationGainDb = " << propagationGainDb << " dB");
328  pathLossDb -= propagationGainDb;
329  }
330  NS_LOG_LOGIC ("total pathLoss = " << pathLossDb << " dB");
331  m_pathLossTrace (txParams->txPhy, *rxPhyIterator, pathLossDb);
332  if ( pathLossDb > m_maxLossDb)
333  {
334  // beyond range
335  continue;
336  }
337  double pathGainLinear = std::pow (10.0, (-pathLossDb) / 10.0);
338  *(rxParams->psd) *= pathGainLinear;
339 
341  {
342  rxParams->psd = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity (rxParams->psd, txMobility, receiverMobility);
343  }
344 
345  if (m_propagationDelay)
346  {
347  delay = m_propagationDelay->GetDelay (txMobility, receiverMobility);
348  }
349  }
350 
351  Ptr<NetDevice> netDev = (*rxPhyIterator)->GetDevice ();
352  if (netDev)
353  {
354  // the receiver has a NetDevice, so we expect that it is attached to a Node
355  uint32_t dstNode = netDev->GetNode ()->GetId ();
357  rxParams, *rxPhyIterator);
358  }
359  else
360  {
361  // the receiver is not attached to a NetDevice, so we cannot assume that it is attached to a node
363  rxParams, *rxPhyIterator);
364  }
365  }
366  }
367 
368  }
369 
370 }
371 
372 void
374 {
375  NS_LOG_FUNCTION (this);
376  receiver->StartRx (params);
377 }
378 
379 
380 
381 uint32_t
383 {
384  return m_numDevices;
385 
386 }
387 
388 
391 {
392  NS_ASSERT (i < m_numDevices);
393  // this method implementation is computationally intensive. This
394  // method would be faster if we actually used a std::vector for
395  // storing devices, which we don't due to the need to have fast
396  // SpectrumModel conversions and to allow PHY devices to changea
397  // SpectrumModel at run time. Note that having this method slow is
398  // acceptable as it is not used much at run time (often not at all).
399  // On the other hand, having slow SpectrumModel conversion would be
400  // less acceptable.
401  uint32_t j = 0;
402  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
403  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
404  ++rxInfoIterator)
405  {
406  for (std::set<Ptr<SpectrumPhy> >::const_iterator phyIt = rxInfoIterator->second.m_rxPhySet.begin ();
407  phyIt != rxInfoIterator->second.m_rxPhySet.end ();
408  ++phyIt)
409  {
410  if (j == i)
411  {
412  return (*phyIt)->GetDevice ();
413  }
414  }
415  }
416  NS_FATAL_ERROR ("m_numDevice > actual number of devices");
417  return 0;
418 }
419 
420 
421 
422 void
424 {
425  NS_LOG_FUNCTION (this << loss);
427  m_propagationLoss = loss;
428 }
429 
430 void
432 {
435 }
436 
437 void
439 {
441  m_propagationDelay = delay;
442 }
443 
446 {
447  NS_LOG_FUNCTION (this);
449 }
450 
451 
452 } // 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:95
#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:61
#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:338
#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
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:84
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:875
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:51
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:631