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);
93  m_txSpectrumModelInfoMap.clear ();
94  m_rxSpectrumModelInfoMap.clear ();
96 }
97 
98 TypeId
100 {
101  static TypeId tid = TypeId ("ns3::MultiModelSpectrumChannel")
103  .SetGroupName ("Spectrum")
104  .AddConstructor<MultiModelSpectrumChannel> ()
105 
106  ;
107  return tid;
108 }
109 
110 
111 
112 void
114 {
115  NS_LOG_FUNCTION (this << phy);
116 
117  Ptr<const SpectrumModel> rxSpectrumModel = phy->GetRxSpectrumModel ();
118 
119  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)");
120 
121  SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
122 
123  // remove a previous entry of this phy if it exists
124  // we need to scan for all rxSpectrumModel values since we don't
125  // know which spectrum model the phy had when it was previously added
126  // (it's probably different than the current one)
127  for (RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
128  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
129  ++rxInfoIterator)
130  {
131  std::set<Ptr<SpectrumPhy> >::iterator phyIt = rxInfoIterator->second.m_rxPhySet.find (phy);
132  if (phyIt != rxInfoIterator->second.m_rxPhySet.end ())
133  {
134  rxInfoIterator->second.m_rxPhySet.erase (phyIt);
135  --m_numDevices;
136  break; // there should be at most one entry
137  }
138  }
139 
140  ++m_numDevices;
141 
142  RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.find (rxSpectrumModelUid);
143 
144  if (rxInfoIterator == m_rxSpectrumModelInfoMap.end ())
145  {
146  // spectrum model unknown, add it to the list of RxSpectrumModels
147  std::pair<RxSpectrumModelInfoMap_t::iterator, bool> ret;
148  ret = m_rxSpectrumModelInfoMap.insert (std::make_pair (rxSpectrumModelUid, RxSpectrumModelInfo (rxSpectrumModel)));
149  NS_ASSERT (ret.second);
150  // also add the phy to the newly created set of SpectrumPhy for this RxSpectrumModel
151  std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = ret.first->second.m_rxPhySet.insert (phy);
152  NS_ASSERT (ret2.second);
153 
154  // and create the necessary converters for all the TX spectrum models that we know of
155  for (TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.begin ();
156  txInfoIterator != m_txSpectrumModelInfoMap.end ();
157  ++txInfoIterator)
158  {
159  Ptr<const SpectrumModel> txSpectrumModel = txInfoIterator->second.m_txSpectrumModel;
160  SpectrumModelUid_t txSpectrumModelUid = txSpectrumModel->GetUid ();
161 
162  if (rxSpectrumModelUid != txSpectrumModelUid && !txSpectrumModel->IsOrthogonal (*rxSpectrumModel))
163  {
164  NS_LOG_LOGIC ("Creating converter between SpectrumModelUid " << txSpectrumModel->GetUid () << " and " << rxSpectrumModelUid);
165  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
166  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
167  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
168  NS_ASSERT (ret2.second);
169  }
170  }
171  }
172  else
173  {
174  // spectrum model is already known, just add the device to the corresponding list
175  std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = rxInfoIterator->second.m_rxPhySet.insert (phy);
176  NS_ASSERT (ret2.second);
177  }
178 
179 }
180 
181 
182 TxSpectrumModelInfoMap_t::const_iterator
184 {
185  NS_LOG_FUNCTION (this << txSpectrumModel);
186  SpectrumModelUid_t txSpectrumModelUid = txSpectrumModel->GetUid ();
187  TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.find (txSpectrumModelUid);
188 
189  if (txInfoIterator == m_txSpectrumModelInfoMap.end ())
190  {
191  // first time we see this TX SpectrumModel
192  // we add it to the list
193  std::pair<TxSpectrumModelInfoMap_t::iterator, bool> ret;
194  ret = m_txSpectrumModelInfoMap.insert (std::make_pair (txSpectrumModelUid, TxSpectrumModelInfo (txSpectrumModel)));
195  NS_ASSERT (ret.second);
196  txInfoIterator = ret.first;
197 
198  // and we create the converters for all the RX SpectrumModels that we know of
199  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
200  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
201  ++rxInfoIterator)
202  {
203  Ptr<const SpectrumModel> rxSpectrumModel = rxInfoIterator->second.m_rxSpectrumModel;
204  SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
205 
206  if (rxSpectrumModelUid != txSpectrumModelUid && !txSpectrumModel->IsOrthogonal (*rxSpectrumModel))
207  {
208  NS_LOG_LOGIC ("Creating converter between SpectrumModelUid " << txSpectrumModelUid << " and " << rxSpectrumModelUid);
209 
210  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
211  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
212  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
213  NS_ASSERT (ret2.second);
214  }
215  }
216  }
217  else
218  {
219  NS_LOG_LOGIC ("SpectrumModelUid " << txSpectrumModelUid << " already present");
220  }
221  return txInfoIterator;
222 }
223 
224 
225 
226 void
228 {
229  NS_LOG_FUNCTION (this << txParams);
230 
231  NS_ASSERT (txParams->txPhy);
232  NS_ASSERT (txParams->psd);
233  Ptr<SpectrumSignalParameters> txParamsTrace = txParams->Copy (); // copy it since traced value cannot be const (because of potential underlying DynamicCasts)
234  m_txSigParamsTrace (txParamsTrace);
235 
236  Ptr<MobilityModel> txMobility = txParams->txPhy->GetMobility ();
237  SpectrumModelUid_t txSpectrumModelUid = txParams->psd->GetSpectrumModelUid ();
238  NS_LOG_LOGIC (" txSpectrumModelUid " << txSpectrumModelUid);
239 
240  //
241  TxSpectrumModelInfoMap_t::const_iterator txInfoIteratorerator = FindAndEventuallyAddTxSpectrumModel (txParams->psd->GetSpectrumModel ());
242  NS_ASSERT (txInfoIteratorerator != m_txSpectrumModelInfoMap.end ());
243 
244  NS_LOG_LOGIC ("converter map for TX SpectrumModel with Uid " << txInfoIteratorerator->first);
245  NS_LOG_LOGIC ("converter map size: " << txInfoIteratorerator->second.m_spectrumConverterMap.size ());
246  NS_LOG_LOGIC ("converter map first element: " << txInfoIteratorerator->second.m_spectrumConverterMap.begin ()->first);
247 
248  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
249  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
250  ++rxInfoIterator)
251  {
252  SpectrumModelUid_t rxSpectrumModelUid = rxInfoIterator->second.m_rxSpectrumModel->GetUid ();
253  NS_LOG_LOGIC (" rxSpectrumModelUids " << rxSpectrumModelUid);
254 
255  Ptr <SpectrumValue> convertedTxPowerSpectrum;
256  if (txSpectrumModelUid == rxSpectrumModelUid)
257  {
258  NS_LOG_LOGIC ("no spectrum conversion needed");
259  convertedTxPowerSpectrum = txParams->psd;
260  }
261  else
262  {
263  NS_LOG_LOGIC (" converting txPowerSpectrum SpectrumModelUids" << txSpectrumModelUid << " --> " << rxSpectrumModelUid);
264  SpectrumConverterMap_t::const_iterator rxConverterIterator = txInfoIteratorerator->second.m_spectrumConverterMap.find (rxSpectrumModelUid);
265  if (rxConverterIterator == txInfoIteratorerator->second.m_spectrumConverterMap.end ())
266  {
267  // No converter means TX SpectrumModel is orthogonal to RX SpectrumModel
268  continue;
269  }
270  convertedTxPowerSpectrum = rxConverterIterator->second.Convert (txParams->psd);
271  }
272 
273 
274  for (std::set<Ptr<SpectrumPhy> >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhySet.begin ();
275  rxPhyIterator != rxInfoIterator->second.m_rxPhySet.end ();
276  ++rxPhyIterator)
277  {
278  NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid,
279  "SpectrumModel change was not notified to MultiModelSpectrumChannel (i.e., AddRx should be called again after model is changed)");
280 
281  if ((*rxPhyIterator) != txParams->txPhy)
282  {
283  NS_LOG_LOGIC (" copying signal parameters " << txParams);
284  Ptr<SpectrumSignalParameters> rxParams = txParams->Copy ();
285  rxParams->psd = Copy<SpectrumValue> (convertedTxPowerSpectrum);
286  Time delay = MicroSeconds (0);
287 
288  Ptr<MobilityModel> receiverMobility = (*rxPhyIterator)->GetMobility ();
289 
290  if (txMobility && receiverMobility)
291  {
292  double pathLossDb = 0;
293  if (rxParams->txAntenna != 0)
294  {
295  Angles txAngles (receiverMobility->GetPosition (), txMobility->GetPosition ());
296  double txAntennaGain = rxParams->txAntenna->GetGainDb (txAngles);
297  NS_LOG_LOGIC ("txAntennaGain = " << txAntennaGain << " dB");
298  pathLossDb -= txAntennaGain;
299  }
300  Ptr<AntennaModel> rxAntenna = (*rxPhyIterator)->GetRxAntenna ();
301  if (rxAntenna != 0)
302  {
303  Angles rxAngles (txMobility->GetPosition (), receiverMobility->GetPosition ());
304  double rxAntennaGain = rxAntenna->GetGainDb (rxAngles);
305  NS_LOG_LOGIC ("rxAntennaGain = " << rxAntennaGain << " dB");
306  pathLossDb -= rxAntennaGain;
307  }
308  if (m_propagationLoss)
309  {
310  double propagationGainDb = m_propagationLoss->CalcRxPower (0, txMobility, receiverMobility);
311  NS_LOG_LOGIC ("propagationGainDb = " << propagationGainDb << " dB");
312  pathLossDb -= propagationGainDb;
313  }
314  NS_LOG_LOGIC ("total pathLoss = " << pathLossDb << " dB");
315  m_pathLossTrace (txParams->txPhy, *rxPhyIterator, pathLossDb);
316  if ( pathLossDb > m_maxLossDb)
317  {
318  // beyond range
319  continue;
320  }
321  double pathGainLinear = std::pow (10.0, (-pathLossDb) / 10.0);
322  *(rxParams->psd) *= pathGainLinear;
323 
325  {
326  rxParams->psd = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity (rxParams->psd, txMobility, receiverMobility);
327  }
328 
329  if (m_propagationDelay)
330  {
331  delay = m_propagationDelay->GetDelay (txMobility, receiverMobility);
332  }
333  }
334 
335  Ptr<NetDevice> netDev = (*rxPhyIterator)->GetDevice ();
336  if (netDev)
337  {
338  // the receiver has a NetDevice, so we expect that it is attached to a Node
339  uint32_t dstNode = netDev->GetNode ()->GetId ();
341  rxParams, *rxPhyIterator);
342  }
343  else
344  {
345  // the receiver is not attached to a NetDevice, so we cannot assume that it is attached to a node
347  rxParams, *rxPhyIterator);
348  }
349  }
350  }
351 
352  }
353 
354 }
355 
356 void
358 {
359  NS_LOG_FUNCTION (this);
360  receiver->StartRx (params);
361 }
362 
363 std::size_t
365 {
366  return m_numDevices;
367 }
368 
371 {
372  NS_ASSERT (i < m_numDevices);
373  // this method implementation is computationally intensive. This
374  // method would be faster if we actually used a std::vector for
375  // storing devices, which we don't due to the need to have fast
376  // SpectrumModel conversions and to allow PHY devices to change a
377  // SpectrumModel at run time. Note that having this method slow is
378  // acceptable as it is not used much at run time (often not at all).
379  // On the other hand, having slow SpectrumModel conversion would be
380  // less acceptable.
381  std::size_t j = 0;
382  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
383  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
384  ++rxInfoIterator)
385  {
386  for (std::set<Ptr<SpectrumPhy> >::const_iterator phyIt = rxInfoIterator->second.m_rxPhySet.begin ();
387  phyIt != rxInfoIterator->second.m_rxPhySet.end ();
388  ++phyIt)
389  {
390  if (j == i)
391  {
392  return (*phyIt)->GetDevice ();
393  }
394  j++;
395  }
396  }
397  NS_FATAL_ERROR ("m_numDevice > actual number of devices");
398  return 0;
399 }
400 
401 } // namespace ns3
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
virtual Ptr< NetDevice > GetDevice(std::size_t i) const
#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.
double CalcRxPower(double txPowerDbm, Ptr< MobilityModel > a, Ptr< MobilityModel > b) const
Returns the Rx Power taking into account all the PropagationLossModel(s) chained to the current one...
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:45
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
TracedCallback< Ptr< const SpectrumPhy >, Ptr< const SpectrumPhy >, double > m_pathLossTrace
The PathLoss trace source.
#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
double m_maxLossDb
Maximum loss [dB].
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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...
This SpectrumChannel implementation can handle the presence of SpectrumPhy instances which can use di...
bool IsOrthogonal(const SpectrumModel &other) const
Check if another SpectrumModels has bands orthogonal to our bands.
SpectrumModelUid_t GetUid() const
std::size_t m_numDevices
Number of devices connected to the channel.
phy
Definition: third.py:86
Class which implements a converter between SpectrumValue which are defined over different SpectrumMod...
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1381
static TypeId GetTypeId(void)
Get the type ID.
Ptr< SpectrumPropagationLossModel > m_spectrumPropagationLoss
Frequency-dependent propagation loss model to be used with this channel.
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...
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.
virtual std::size_t GetNDevices(void) const
RxSpectrumModelInfo(Ptr< const SpectrumModel > rxSpectrumModel)
Constructor.
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
void DoDispose()
Destructor implementation.
Vector GetPosition(void) const
static void ScheduleWithContext(uint32_t context, Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event with the given context.
Definition: simulator.h:1475
virtual void StartTx(Ptr< SpectrumSignalParameters > params)
Used by attached PHY instances to transmit signals on the channel.
Ptr< PropagationLossModel > m_propagationLoss
Single-frequency propagation loss model to be used with this channel.
TracedCallback< Ptr< SpectrumSignalParameters > > m_txSigParamsTrace
Traced callback for SpectrumSignalParameters in StartTx requests.
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.
Ptr< PropagationDelayModel > m_propagationDelay
Propagation delay model to be used with this channel.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1030
struct holding the azimuth and inclination angles of spherical coordinates.
Definition: angles.h:71
TxSpectrumModelInfo(Ptr< const SpectrumModel > txSpectrumModel)
Constructor.
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:915
virtual void DoDispose(void)
Destructor implementation.
std::map< SpectrumModelUid_t, TxSpectrumModelInfo > TxSpectrumModelInfoMap_t
Container: SpectrumModelUid_t, TxSpectrumModelInfo.
The Tx spectrum model information.