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 std::ostream& operator<< (std::ostream& lhs, TxSpectrumModelInfoMap_t& rhs)
52 {
53  for (TxSpectrumModelInfoMap_t::iterator it = rhs.begin ();
54  it != rhs.end ();
55  ++it)
56  {
57  SpectrumConverterMap_t::iterator jt;
58  for (jt = it->second.m_spectrumConverterMap.begin ();
59  jt != it->second.m_spectrumConverterMap.end ();
60  ++jt)
61  {
62  lhs << "(" << it->first << "," << jt->first << ") ";
63  }
64  }
65  return lhs;
66 }
67 
69  : m_txSpectrumModel (txSpectrumModel)
70 {
71 }
72 
73 
75  : m_rxSpectrumModel (rxSpectrumModel)
76 {
77 }
78 
79 
81 {
82  NS_LOG_FUNCTION (this);
83 }
84 
85 void
87 {
88  NS_LOG_FUNCTION (this);
92  m_txSpectrumModelInfoMap.clear ();
93  m_rxSpectrumModelInfoMap.clear ();
94  m_phyVector.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  // make sure this phy had not been already added
146  for ( it = m_phyVector.begin (); it != m_phyVector.end (); ++it)
147  {
148  NS_ASSERT (*it != phy);
149  }
150  m_phyVector.push_back (phy);
151 
152  RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.find (rxSpectrumModelUid);
153 
154  if (rxInfoIterator == m_rxSpectrumModelInfoMap.end ())
155  {
156  // spectrum model unknown, add it to the list of RxSpectrumModels
157  std::pair<RxSpectrumModelInfoMap_t::iterator, bool> ret;
158  ret = m_rxSpectrumModelInfoMap.insert (std::make_pair (rxSpectrumModelUid, RxSpectrumModelInfo (rxSpectrumModel)));
159  NS_ASSERT (ret.second);
160  // also add the phy to the newly created list of SpectrumPhy for this RxSpectrumModel
161  ret.first->second.m_rxPhyList.push_back (phy);
162 
163  // and create the necessary converters for all the TX spectrum models that we know of
164  for (TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.begin ();
165  txInfoIterator != m_txSpectrumModelInfoMap.end ();
166  ++txInfoIterator)
167  {
168  Ptr<const SpectrumModel> txSpectrumModel = txInfoIterator->second.m_txSpectrumModel;
169  NS_LOG_LOGIC ("Creating converters between SpectrumModelUids " << txSpectrumModel->GetUid () << " and " << rxSpectrumModelUid );
170  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
171  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
172  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
173  NS_ASSERT (ret2.second);
174  }
175  }
176  else
177  {
178  // spectrum model is already known, just add the device to the corresponding list
179  rxInfoIterator->second.m_rxPhyList.push_back (phy);
180  }
181 
182 }
183 
184 
185 TxSpectrumModelInfoMap_t::const_iterator
187 {
188  NS_LOG_FUNCTION (this << txSpectrumModel);
189  SpectrumModelUid_t txSpectrumModelUid = txSpectrumModel->GetUid ();
190  TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.find (txSpectrumModelUid);
191 
192  if (txInfoIterator == m_txSpectrumModelInfoMap.end ())
193  {
194  // first time we see this TX SpectrumModel
195  // we add it to the list
196  std::pair<TxSpectrumModelInfoMap_t::iterator, bool> ret;
197  ret = m_txSpectrumModelInfoMap.insert (std::make_pair (txSpectrumModelUid, TxSpectrumModelInfo (txSpectrumModel)));
198  NS_ASSERT (ret.second);
199  txInfoIterator = ret.first;
200 
201  // and we create the converters for all the RX SpectrumModels that we know of
202  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
203  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
204  ++rxInfoIterator)
205  {
206  Ptr<const SpectrumModel> rxSpectrumModel = rxInfoIterator->second.m_rxSpectrumModel;
207  SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
208 
209  if (rxSpectrumModelUid != txSpectrumModelUid)
210  {
211  NS_LOG_LOGIC ("Creating converters between SpectrumModelUids " << txSpectrumModelUid << " and " << rxSpectrumModelUid );
212 
213  SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
214  std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
215  ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
216  NS_ASSERT (ret2.second);
217  }
218  }
219  }
220  else
221  {
222  NS_LOG_LOGIC ("SpectrumModelUid " << txSpectrumModelUid << " already present");
223  }
224  return txInfoIterator;
225 }
226 
227 
228 void
230 {
231  NS_LOG_FUNCTION (this << txParams);
232 
233  NS_ASSERT (txParams->txPhy);
234  NS_ASSERT (txParams->psd);
235 
236 
237  Ptr<MobilityModel> txMobility = txParams->txPhy->GetMobility ();
238  SpectrumModelUid_t txSpectrumModelUid = txParams->psd->GetSpectrumModelUid ();
239  NS_LOG_LOGIC (" txSpectrumModelUid " << txSpectrumModelUid);
240 
241  //
242  TxSpectrumModelInfoMap_t::const_iterator txInfoIteratorerator = FindAndEventuallyAddTxSpectrumModel (txParams->psd->GetSpectrumModel ());
243  NS_ASSERT (txInfoIteratorerator != m_txSpectrumModelInfoMap.end ());
244 
245  NS_LOG_LOGIC ("converter map for TX SpectrumModel with Uid " << txInfoIteratorerator->first);
246  NS_LOG_LOGIC ("converter map size: " << txInfoIteratorerator->second.m_spectrumConverterMap.size ());
247  NS_LOG_LOGIC ("converter map first element: " << txInfoIteratorerator->second.m_spectrumConverterMap.begin ()->first);
248 
249  for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
250  rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
251  ++rxInfoIterator)
252  {
253  SpectrumModelUid_t rxSpectrumModelUid = rxInfoIterator->second.m_rxSpectrumModel->GetUid ();
254  NS_LOG_LOGIC (" rxSpectrumModelUids " << rxSpectrumModelUid);
255 
256  Ptr <SpectrumValue> convertedTxPowerSpectrum;
257  if (txSpectrumModelUid == rxSpectrumModelUid)
258  {
259  NS_LOG_LOGIC ("no spectrum conversion needed");
260  convertedTxPowerSpectrum = txParams->psd;
261  }
262  else
263  {
264  NS_LOG_LOGIC (" converting txPowerSpectrum SpectrumModelUids" << txSpectrumModelUid << " --> " << rxSpectrumModelUid);
265  SpectrumConverterMap_t::const_iterator rxConverterIterator = txInfoIteratorerator->second.m_spectrumConverterMap.find (rxSpectrumModelUid);
266  NS_ASSERT (rxConverterIterator != txInfoIteratorerator->second.m_spectrumConverterMap.end ());
267  convertedTxPowerSpectrum = rxConverterIterator->second.Convert (txParams->psd);
268  }
269 
270 
271  for (std::list<Ptr<SpectrumPhy> >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhyList.begin ();
272  rxPhyIterator != rxInfoIterator->second.m_rxPhyList.end ();
273  ++rxPhyIterator)
274  {
275  NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid,
276  "MultiModelSpectrumChannel only supports devices that use a single RxSpectrumModel that does not change for the whole simulation");
277 
278 
279 
280  if ((*rxPhyIterator) != txParams->txPhy)
281  {
282  NS_LOG_LOGIC (" copying signal parameters " << txParams);
283  Ptr<SpectrumSignalParameters> rxParams = txParams->Copy ();
284  rxParams->psd = Copy<SpectrumValue> (convertedTxPowerSpectrum);
285  Time delay = MicroSeconds (0);
286 
287  Ptr<MobilityModel> receiverMobility = (*rxPhyIterator)->GetMobility ();
288 
289  if (txMobility && receiverMobility)
290  {
291  double pathLossDb = 0;
292  if (rxParams->txAntenna != 0)
293  {
294  Angles txAngles (receiverMobility->GetPosition (), txMobility->GetPosition ());
295  double txAntennaGain = rxParams->txAntenna->GetGainDb (txAngles);
296  NS_LOG_LOGIC ("txAntennaGain = " << txAntennaGain << " dB");
297  pathLossDb -= txAntennaGain;
298  }
299  Ptr<AntennaModel> rxAntenna = (*rxPhyIterator)->GetRxAntenna ();
300  if (rxAntenna != 0)
301  {
302  Angles rxAngles (txMobility->GetPosition (), receiverMobility->GetPosition ());
303  double rxAntennaGain = rxAntenna->GetGainDb (rxAngles);
304  NS_LOG_LOGIC ("rxAntennaGain = " << rxAntennaGain << " dB");
305  pathLossDb -= rxAntennaGain;
306  }
307  if (m_propagationLoss)
308  {
309  double propagationGainDb = m_propagationLoss->CalcRxPower (0, txMobility, receiverMobility);
310  NS_LOG_LOGIC ("propagationGainDb = " << propagationGainDb << " dB");
311  pathLossDb -= propagationGainDb;
312  }
313  NS_LOG_LOGIC ("total pathLoss = " << pathLossDb << " dB");
314  m_pathLossTrace (txParams->txPhy, *rxPhyIterator, pathLossDb);
315  if ( pathLossDb > m_maxLossDb)
316  {
317  // beyond range
318  continue;
319  }
320  double pathGainLinear = pow (10.0, (-pathLossDb) / 10.0);
321  *(rxParams->psd) *= pathGainLinear;
322 
324  {
325  rxParams->psd = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity (rxParams->psd, txMobility, receiverMobility);
326  }
327 
328  if (m_propagationDelay)
329  {
330  delay = m_propagationDelay->GetDelay (txMobility, receiverMobility);
331  }
332  }
333 
334  Ptr<NetDevice> netDev = (*rxPhyIterator)->GetDevice ();
335  if (netDev)
336  {
337  // the receiver has a NetDevice, so we expect that it is attached to a Node
338  uint32_t dstNode = netDev->GetNode ()->GetId ();
340  rxParams, *rxPhyIterator);
341  }
342  else
343  {
344  // the receiver is not attached to a NetDevice, so we cannot assume that it is attached to a node
346  rxParams, *rxPhyIterator);
347  }
348  }
349  }
350 
351  }
352 
353 }
354 
355 void
357 {
358  NS_LOG_FUNCTION (this);
359  receiver->StartRx (params);
360 }
361 
362 
363 
364 uint32_t
366 {
367  return m_phyVector.size ();
368 
369 }
370 
371 
374 {
375  return m_phyVector.at (i)->GetDevice ();
376 }
377 
378 
379 
380 void
382 {
383  NS_LOG_FUNCTION (this << loss);
385  m_propagationLoss = loss;
386 }
387 
388 void
390 {
393 }
394 
395 void
397 {
399  m_propagationDelay = delay;
400 }
401 
404 {
405  NS_LOG_FUNCTION (this);
407 }
408 
409 
410 } // namespace ns3