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