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
Class holding the azimuth and inclination angles of spherical coordinates.
Definition: angles.h:119
virtual double GetGainDb(Angles a)=0
this method is expected to be re-implemented by each antenna model
Vector GetPosition(void) const
This SpectrumChannel implementation can handle the presence of SpectrumPhy instances which can use di...
virtual std::size_t GetNDevices(void) const
TxSpectrumModelInfoMap_t m_txSpectrumModelInfoMap
Data structure holding, for each TX SpectrumModel, all the converters to any RX SpectrumModel,...
std::size_t m_numDevices
Number of devices connected to the channel.
static TypeId GetTypeId(void)
Get the type ID.
TxSpectrumModelInfoMap_t::const_iterator FindAndEventuallyAddTxSpectrumModel(Ptr< const SpectrumModel > txSpectrumModel)
This method checks if m_rxSpectrumModelInfoMap contains an entry for the given TX SpectrumModel.
void DoDispose()
Destructor implementation.
virtual void StartRx(Ptr< SpectrumSignalParameters > params, Ptr< SpectrumPhy > receiver)
Used internally to reschedule transmission after the propagation delay.
virtual void StartTx(Ptr< SpectrumSignalParameters > params)
Used by attached PHY instances to transmit signals on the channel.
virtual Ptr< NetDevice > GetDevice(std::size_t i) const
virtual void AddRx(Ptr< SpectrumPhy > phy)
Add a SpectrumPhy to a channel, so it can receive packets.
RxSpectrumModelInfoMap_t m_rxSpectrumModelInfoMap
Data structure holding, for each RX spectrum model, all the corresponding SpectrumPhy instances.
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.
The Rx spectrum model information.
RxSpectrumModelInfo(Ptr< const SpectrumModel > rxSpectrumModel)
Constructor.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
static void ScheduleWithContext(uint32_t context, Time const &delay, FUNC f, Ts &&... args)
Schedule an event with the given context.
Definition: simulator.h:572
Defines the interface for spectrum-aware channel implementations.
TracedCallback< Ptr< const SpectrumPhy >, Ptr< const SpectrumPhy >, double > m_pathLossTrace
The PathLoss trace source.
TracedCallback< Ptr< SpectrumSignalParameters > > m_txSigParamsTrace
Traced callback for SpectrumSignalParameters in StartTx requests.
Ptr< PropagationDelayModel > m_propagationDelay
Propagation delay model to be used with this channel.
virtual void DoDispose(void)
Destructor implementation.
Ptr< SpectrumPropagationLossModel > m_spectrumPropagationLoss
Frequency-dependent propagation loss model to be used with this channel.
TracedCallback< Ptr< const MobilityModel >, Ptr< const MobilityModel >, double, double, double, double > m_gainTrace
The Gain trace source.
Ptr< PropagationLossModel > m_propagationLoss
Single-frequency propagation loss model to be used with this channel.
double m_maxLossDb
Maximum loss [dB].
Class which implements a converter between SpectrumValue which are defined over different SpectrumMod...
bool IsOrthogonal(const SpectrumModel &other) const
Check if another SpectrumModels has bands orthogonal to our bands.
SpectrumModelUid_t GetUid() const
virtual void StartRx(Ptr< SpectrumSignalParameters > params)=0
Notify the SpectrumPhy instance of an incoming signal.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
The Tx spectrum model information.
TxSpectrumModelInfo(Ptr< const SpectrumModel > txSpectrumModel)
Constructor.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
#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_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:88
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
std::map< SpectrumModelUid_t, TxSpectrumModelInfo > TxSpectrumModelInfoMap_t
Container: SpectrumModelUid_t, TxSpectrumModelInfo.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1305
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t SpectrumModelUid_t
Uid for SpectrumModels.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:137
phy
Definition: third.py:93