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 <algorithm>
22 #include <iostream>
23 #include <utility>
24 #include <ns3/object.h>
25 #include <ns3/simulator.h>
26 #include <ns3/log.h>
27 #include <ns3/packet.h>
28 #include <ns3/packet-burst.h>
29 #include <ns3/net-device.h>
30 #include <ns3/node.h>
31 #include <ns3/double.h>
32 #include <ns3/mobility-model.h>
33 #include <ns3/spectrum-phy.h>
34 #include <ns3/spectrum-converter.h>
35 #include <ns3/spectrum-propagation-loss-model.h>
36 #include <ns3/propagation-loss-model.h>
37 #include <ns3/propagation-delay-model.h>
38 #include <ns3/antenna-model.h>
39 #include <ns3/angles.h>
41 
42 namespace ns3 {
43 
44 NS_LOG_COMPONENT_DEFINE ("MultiModelSpectrumChannel");
45 
46 NS_OBJECT_ENSURE_REGISTERED (MultiModelSpectrumChannel);
47 
54 std::ostream& operator<< (std::ostream& lhs, TxSpectrumModelInfoMap_t& rhs)
55 {
56  for (TxSpectrumModelInfoMap_t::iterator it = rhs.begin ();
57  it != rhs.end ();
58  ++it)
59  {
60  SpectrumConverterMap_t::iterator jt;
61  for (jt = it->second.m_spectrumConverterMap.begin ();
62  jt != it->second.m_spectrumConverterMap.end ();
63  ++jt)
64  {
65  lhs << "(" << it->first << "," << jt->first << ") ";
66  }
67  }
68  return lhs;
69 }
70 
72  : m_txSpectrumModel (txSpectrumModel)
73 {
74 }
75 
77  : m_rxSpectrumModel (rxSpectrumModel)
78 {
79 }
80 
82  : m_numDevices {0}
83 {
84  NS_LOG_FUNCTION (this);
85 }
86 
87 void
89 {
90  NS_LOG_FUNCTION (this);
91  m_txSpectrumModelInfoMap.clear ();
92  m_rxSpectrumModelInfoMap.clear ();
94 }
95 
96 TypeId
98 {
99  static TypeId tid = TypeId ("ns3::MultiModelSpectrumChannel")
101  .SetGroupName ("Spectrum")
102  .AddConstructor<MultiModelSpectrumChannel> ()
103 
104  ;
105  return tid;
106 }
107 
108 void
110 {
111  NS_LOG_FUNCTION (this << phy);
112 
113  Ptr<const SpectrumModel> rxSpectrumModel = phy->GetRxSpectrumModel ();
114 
115  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)");
116 
117  SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
118 
119  // remove a previous entry of this phy if it exists
120  // we need to scan for all rxSpectrumModel values since we don't
121  // know which spectrum model the phy had when it was previously added
122  // (it's probably different than the current one)
123  for (RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
124  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
125  ++rxInfoIterator)
126  {
127  auto phyIt = std::find (rxInfoIterator->second.m_rxPhys.begin(), rxInfoIterator->second.m_rxPhys.end(), phy);
128  if (phyIt != rxInfoIterator->second.m_rxPhys.end ())
129  {
130  rxInfoIterator->second.m_rxPhys.erase (phyIt);
131  --m_numDevices;
132  break; // there should be at most one entry
133  }
134  }
135 
136  ++m_numDevices;
137 
138  RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.find (rxSpectrumModelUid);
139 
140  if (rxInfoIterator == m_rxSpectrumModelInfoMap.end ())
141  {
142  // spectrum model unknown, add it to the list of RxSpectrumModels
143  std::pair<RxSpectrumModelInfoMap_t::iterator, bool> ret;
144  ret = m_rxSpectrumModelInfoMap.insert (std::make_pair (rxSpectrumModelUid, RxSpectrumModelInfo (rxSpectrumModel)));
145  NS_ASSERT (ret.second);
146  // also add the phy to the newly created set of SpectrumPhy for this RxSpectrumModel
147  ret.first->second.m_rxPhys.push_back (phy);
148 
149  // and create the necessary converters for all the TX spectrum models that we know of
150  for (TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.begin ();
151  txInfoIterator != m_txSpectrumModelInfoMap.end ();
152  ++txInfoIterator)
153  {
154  Ptr<const SpectrumModel> txSpectrumModel = txInfoIterator->second.m_txSpectrumModel;
155  SpectrumModelUid_t txSpectrumModelUid = txSpectrumModel->GetUid ();
156 
157  if (rxSpectrumModelUid != txSpectrumModelUid && !txSpectrumModel->IsOrthogonal (*rxSpectrumModel))
158  {
159  NS_LOG_LOGIC ("Creating converter between SpectrumModelUid " << txSpectrumModel->GetUid () << " and " << rxSpectrumModelUid);
160  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
161  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
162  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
163  NS_ASSERT (ret2.second);
164  }
165  }
166  }
167  else
168  {
169  // spectrum model is already known, just add the device to the corresponding list
170  rxInfoIterator->second.m_rxPhys.push_back (phy);
171  }
172 }
173 
174 TxSpectrumModelInfoMap_t::const_iterator
176 {
177  NS_LOG_FUNCTION (this << txSpectrumModel);
178  SpectrumModelUid_t txSpectrumModelUid = txSpectrumModel->GetUid ();
179  TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.find (txSpectrumModelUid);
180 
181  if (txInfoIterator == m_txSpectrumModelInfoMap.end ())
182  {
183  // first time we see this TX SpectrumModel
184  // we add it to the list
185  std::pair<TxSpectrumModelInfoMap_t::iterator, bool> ret;
186  ret = m_txSpectrumModelInfoMap.insert (std::make_pair (txSpectrumModelUid, TxSpectrumModelInfo (txSpectrumModel)));
187  NS_ASSERT (ret.second);
188  txInfoIterator = ret.first;
189 
190  // and we create the converters for all the RX SpectrumModels that we know of
191  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
192  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
193  ++rxInfoIterator)
194  {
195  Ptr<const SpectrumModel> rxSpectrumModel = rxInfoIterator->second.m_rxSpectrumModel;
196  SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
197 
198  if (rxSpectrumModelUid != txSpectrumModelUid && !txSpectrumModel->IsOrthogonal (*rxSpectrumModel))
199  {
200  NS_LOG_LOGIC ("Creating converter between SpectrumModelUid " << txSpectrumModelUid << " and " << rxSpectrumModelUid);
201 
202  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
203  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
204  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
205  NS_ASSERT (ret2.second);
206  }
207  }
208  }
209  else
210  {
211  NS_LOG_LOGIC ("SpectrumModelUid " << txSpectrumModelUid << " already present");
212  }
213  return txInfoIterator;
214 }
215 
216 void
218 {
219  NS_LOG_FUNCTION (this << txParams);
220 
221  NS_ASSERT (txParams->txPhy);
222  NS_ASSERT (txParams->psd);
223  Ptr<SpectrumSignalParameters> txParamsTrace = txParams->Copy (); // copy it since traced value cannot be const (because of potential underlying DynamicCasts)
224  m_txSigParamsTrace (txParamsTrace);
225 
226  Ptr<MobilityModel> txMobility = txParams->txPhy->GetMobility ();
227  SpectrumModelUid_t txSpectrumModelUid = txParams->psd->GetSpectrumModelUid ();
228  NS_LOG_LOGIC ("txSpectrumModelUid " << txSpectrumModelUid);
229 
230  //
231  TxSpectrumModelInfoMap_t::const_iterator txInfoIteratorerator = FindAndEventuallyAddTxSpectrumModel (txParams->psd->GetSpectrumModel ());
232  NS_ASSERT (txInfoIteratorerator != m_txSpectrumModelInfoMap.end ());
233 
234  NS_LOG_LOGIC ("converter map for TX SpectrumModel with Uid " << txInfoIteratorerator->first);
235  NS_LOG_LOGIC ("converter map size: " << txInfoIteratorerator->second.m_spectrumConverterMap.size ());
236  NS_LOG_LOGIC ("converter map first element: " << txInfoIteratorerator->second.m_spectrumConverterMap.begin ()->first);
237 
238  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
239  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
240  ++rxInfoIterator)
241  {
242  SpectrumModelUid_t rxSpectrumModelUid = rxInfoIterator->second.m_rxSpectrumModel->GetUid ();
243  NS_LOG_LOGIC ("rxSpectrumModelUids " << rxSpectrumModelUid);
244 
245  Ptr <SpectrumValue> convertedTxPowerSpectrum;
246  if (txSpectrumModelUid == rxSpectrumModelUid)
247  {
248  NS_LOG_LOGIC ("no spectrum conversion needed");
249  convertedTxPowerSpectrum = txParams->psd;
250  }
251  else
252  {
253  NS_LOG_LOGIC ("converting txPowerSpectrum SpectrumModelUids" << txSpectrumModelUid << " --> " << rxSpectrumModelUid);
254  SpectrumConverterMap_t::const_iterator rxConverterIterator = txInfoIteratorerator->second.m_spectrumConverterMap.find (rxSpectrumModelUid);
255  if (rxConverterIterator == txInfoIteratorerator->second.m_spectrumConverterMap.end ())
256  {
257  // No converter means TX SpectrumModel is orthogonal to RX SpectrumModel
258  continue;
259  }
260  convertedTxPowerSpectrum = rxConverterIterator->second.Convert (txParams->psd);
261  }
262 
263  for (auto rxPhyIterator = rxInfoIterator->second.m_rxPhys.begin ();
264  rxPhyIterator != rxInfoIterator->second.m_rxPhys.end ();
265  ++rxPhyIterator)
266  {
267  NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid,
268  "SpectrumModel change was not notified to MultiModelSpectrumChannel (i.e., AddRx should be called again after model is changed)");
269 
270  if ((*rxPhyIterator) != txParams->txPhy)
271  {
272  NS_LOG_LOGIC ("copying signal parameters " << txParams);
273  Ptr<SpectrumSignalParameters> rxParams = txParams->Copy ();
274  rxParams->psd = Copy<SpectrumValue> (convertedTxPowerSpectrum);
275  Time delay = MicroSeconds (0);
276 
277  Ptr<MobilityModel> receiverMobility = (*rxPhyIterator)->GetMobility ();
278 
279  if (txMobility && receiverMobility)
280  {
281  double txAntennaGain = 0;
282  double rxAntennaGain = 0;
283  double propagationGainDb = 0;
284  double pathLossDb = 0;
285  if (rxParams->txAntenna != 0)
286  {
287  Angles txAngles (receiverMobility->GetPosition (), txMobility->GetPosition ());
288  txAntennaGain = rxParams->txAntenna->GetGainDb (txAngles);
289  NS_LOG_LOGIC ("txAntennaGain = " << txAntennaGain << " dB");
290  pathLossDb -= txAntennaGain;
291  }
292  Ptr<AntennaModel> rxAntenna = (*rxPhyIterator)->GetRxAntenna ();
293  if (rxAntenna != 0)
294  {
295  Angles rxAngles (txMobility->GetPosition (), receiverMobility->GetPosition ());
296  rxAntennaGain = rxAntenna->GetGainDb (rxAngles);
297  NS_LOG_LOGIC ("rxAntennaGain = " << rxAntennaGain << " dB");
298  pathLossDb -= rxAntennaGain;
299  }
300  if (m_propagationLoss)
301  {
302  propagationGainDb = m_propagationLoss->CalcRxPower (0, txMobility, receiverMobility);
303  NS_LOG_LOGIC ("propagationGainDb = " << propagationGainDb << " dB");
304  pathLossDb -= propagationGainDb;
305  }
306  NS_LOG_LOGIC ("total pathLoss = " << pathLossDb << " dB");
307  // Gain trace
308  m_gainTrace (txMobility, receiverMobility, txAntennaGain, rxAntennaGain, propagationGainDb, pathLossDb);
309  // Pathloss trace
310  m_pathLossTrace (txParams->txPhy, *rxPhyIterator, pathLossDb);
311  if (pathLossDb > m_maxLossDb)
312  {
313  // beyond range
314  continue;
315  }
316  double pathGainLinear = std::pow (10.0, (-pathLossDb) / 10.0);
317  *(rxParams->psd) *= pathGainLinear;
318 
320  {
321  rxParams->psd = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity (rxParams->psd, txMobility, receiverMobility);
322  }
323 
324  if (m_propagationDelay)
325  {
326  delay = m_propagationDelay->GetDelay (txMobility, receiverMobility);
327  }
328  }
329 
330  Ptr<NetDevice> netDev = (*rxPhyIterator)->GetDevice ();
331  if (netDev)
332  {
333  // the receiver has a NetDevice, so we expect that it is attached to a Node
334  uint32_t dstNode = netDev->GetNode ()->GetId ();
336  rxParams, *rxPhyIterator);
337  }
338  else
339  {
340  // the receiver is not attached to a NetDevice, so we cannot assume that it is attached to a node
342  rxParams, *rxPhyIterator);
343  }
344  }
345  }
346 
347  }
348 
349 }
350 
351 void
353 {
354  NS_LOG_FUNCTION (this);
355  receiver->StartRx (params);
356 }
357 
358 std::size_t
360 {
361  return m_numDevices;
362 }
363 
366 {
367  NS_ASSERT (i < m_numDevices);
368  // this method implementation is computationally intensive. This
369  // method would be faster if we actually used a std::vector for
370  // storing devices, which we don't due to the need to have fast
371  // SpectrumModel conversions and to allow PHY devices to change a
372  // SpectrumModel at run time. Note that having this method slow is
373  // acceptable as it is not used much at run time (often not at all).
374  // On the other hand, having slow SpectrumModel conversion would be
375  // less acceptable.
376  std::size_t j = 0;
377  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
378  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
379  ++rxInfoIterator)
380  {
381  for (const auto &phyIt : rxInfoIterator->second.m_rxPhys)
382  {
383  if (j == i)
384  {
385  return (*phyIt).GetDevice ();
386  }
387  j++;
388  }
389  }
390  NS_FATAL_ERROR ("m_numDevices > actual number of devices");
391  return 0;
392 }
393 
394 } // 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:204
#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:1389
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:1483
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:1078
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.
TracedCallback< Ptr< const MobilityModel >, Ptr< const MobilityModel >, double, double, double, double > m_gainTrace
The Gain trace source.
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.