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
42namespace ns3 {
43
44NS_LOG_COMPONENT_DEFINE ("MultiModelSpectrumChannel");
45
46NS_OBJECT_ENSURE_REGISTERED (MultiModelSpectrumChannel);
47
54std::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
87void
89{
90 NS_LOG_FUNCTION (this);
94}
95
98{
99 static TypeId tid = TypeId ("ns3::MultiModelSpectrumChannel")
101 .SetGroupName ("Spectrum")
102 .AddConstructor<MultiModelSpectrumChannel> ()
103
104 ;
105 return tid;
106}
107
108void
110{
111 NS_LOG_FUNCTION (this << phy);
112
113 // remove a previous entry of this phy if it exists
114 // we need to scan for all rxSpectrumModel values since we don't
115 // know which spectrum model the phy had when it was previously added
116 // (it's probably different than the current one)
117 for (RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
118 rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
119 ++rxInfoIterator)
120 {
121 auto phyIt = std::find (rxInfoIterator->second.m_rxPhys.begin(), rxInfoIterator->second.m_rxPhys.end(), phy);
122 if (phyIt != rxInfoIterator->second.m_rxPhys.end ())
123 {
124 rxInfoIterator->second.m_rxPhys.erase (phyIt);
125 --m_numDevices;
126 break; // there should be at most one entry
127 }
128 }
129}
130
131void
133{
134 NS_LOG_FUNCTION (this << phy);
135
136 Ptr<const SpectrumModel> rxSpectrumModel = phy->GetRxSpectrumModel ();
137
138 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)");
139
140 SpectrumModelUid_t rxSpectrumModelUid = rxSpectrumModel->GetUid ();
141
142 RemoveRx (phy);
143
144 ++m_numDevices;
145
146 RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.find (rxSpectrumModelUid);
147
148 if (rxInfoIterator == m_rxSpectrumModelInfoMap.end ())
149 {
150 // spectrum model unknown, add it to the list of RxSpectrumModels
151 std::pair<RxSpectrumModelInfoMap_t::iterator, bool> ret;
152 ret = m_rxSpectrumModelInfoMap.insert (std::make_pair (rxSpectrumModelUid, RxSpectrumModelInfo (rxSpectrumModel)));
153 NS_ASSERT (ret.second);
154 // also add the phy to the newly created set of SpectrumPhy for this RxSpectrumModel
155 ret.first->second.m_rxPhys.push_back (phy);
156
157 // and create the necessary converters for all the TX spectrum models that we know of
158 for (TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.begin ();
159 txInfoIterator != m_txSpectrumModelInfoMap.end ();
160 ++txInfoIterator)
161 {
162 Ptr<const SpectrumModel> txSpectrumModel = txInfoIterator->second.m_txSpectrumModel;
163 SpectrumModelUid_t txSpectrumModelUid = txSpectrumModel->GetUid ();
164
165 if (rxSpectrumModelUid != txSpectrumModelUid && !txSpectrumModel->IsOrthogonal (*rxSpectrumModel))
166 {
167 NS_LOG_LOGIC ("Creating converter between SpectrumModelUid " << txSpectrumModel->GetUid () << " and " << rxSpectrumModelUid);
168 SpectrumConverter converter (txSpectrumModel, rxSpectrumModel);
169 std::pair<SpectrumConverterMap_t::iterator, bool> ret2;
170 ret2 = txInfoIterator->second.m_spectrumConverterMap.insert (std::make_pair (rxSpectrumModelUid, converter));
171 NS_ASSERT (ret2.second);
172 }
173 }
174 }
175 else
176 {
177 // spectrum model is already known, just add the device to the corresponding list
178 rxInfoIterator->second.m_rxPhys.push_back (phy);
179 }
180}
181
182TxSpectrumModelInfoMap_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
224void
226{
227 NS_LOG_FUNCTION (this << txParams);
228
229 NS_ASSERT (txParams->txPhy);
230 NS_ASSERT (txParams->psd);
231 Ptr<SpectrumSignalParameters> txParamsTrace = txParams->Copy (); // copy it since traced value cannot be const (because of potential underlying DynamicCasts)
232 m_txSigParamsTrace (txParamsTrace);
233
234 Ptr<MobilityModel> txMobility = txParams->txPhy->GetMobility ();
235 SpectrumModelUid_t txSpectrumModelUid = txParams->psd->GetSpectrumModelUid ();
236 NS_LOG_LOGIC ("txSpectrumModelUid " << txSpectrumModelUid);
237
238 //
239 TxSpectrumModelInfoMap_t::const_iterator txInfoIteratorerator = FindAndEventuallyAddTxSpectrumModel (txParams->psd->GetSpectrumModel ());
240 NS_ASSERT (txInfoIteratorerator != m_txSpectrumModelInfoMap.end ());
241
242 NS_LOG_LOGIC ("converter map for TX SpectrumModel with Uid " << txInfoIteratorerator->first);
243 NS_LOG_LOGIC ("converter map size: " << txInfoIteratorerator->second.m_spectrumConverterMap.size ());
244 NS_LOG_LOGIC ("converter map first element: " << txInfoIteratorerator->second.m_spectrumConverterMap.begin ()->first);
245
246 for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
247 rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
248 ++rxInfoIterator)
249 {
250 SpectrumModelUid_t rxSpectrumModelUid = rxInfoIterator->second.m_rxSpectrumModel->GetUid ();
251 NS_LOG_LOGIC ("rxSpectrumModelUids " << rxSpectrumModelUid);
252
253 Ptr <SpectrumValue> convertedTxPowerSpectrum;
254 if (txSpectrumModelUid == rxSpectrumModelUid)
255 {
256 NS_LOG_LOGIC ("no spectrum conversion needed");
257 convertedTxPowerSpectrum = txParams->psd;
258 }
259 else
260 {
261 NS_LOG_LOGIC ("converting txPowerSpectrum SpectrumModelUids " << txSpectrumModelUid << " --> " << rxSpectrumModelUid);
262 SpectrumConverterMap_t::const_iterator rxConverterIterator = txInfoIteratorerator->second.m_spectrumConverterMap.find (rxSpectrumModelUid);
263 if (rxConverterIterator == txInfoIteratorerator->second.m_spectrumConverterMap.end ())
264 {
265 // No converter means TX SpectrumModel is orthogonal to RX SpectrumModel
266 continue;
267 }
268 convertedTxPowerSpectrum = rxConverterIterator->second.Convert (txParams->psd);
269 }
270
271 for (auto rxPhyIterator = rxInfoIterator->second.m_rxPhys.begin ();
272 rxPhyIterator != rxInfoIterator->second.m_rxPhys.end ();
273 ++rxPhyIterator)
274 {
275 NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid,
276 "SpectrumModel change was not notified to MultiModelSpectrumChannel (i.e., AddRx should be called again after model is changed)");
277
278 if ((*rxPhyIterator) != txParams->txPhy)
279 {
280 Ptr<NetDevice> rxNetDevice = (*rxPhyIterator)->GetDevice ();
281 Ptr<NetDevice> txNetDevice = txParams->txPhy->GetDevice ();
282
283 if (rxNetDevice && txNetDevice)
284 {
285 // we assume that devices are attached to a node
286 if (rxNetDevice->GetNode()->GetId() == txNetDevice->GetNode()->GetId())
287 {
288 NS_LOG_DEBUG ("Skipping the pathloss calculation among different antennas of the same node, not supported yet by any pathloss model in ns-3.");
289 continue;
290 }
291 }
292
293 NS_LOG_LOGIC ("copying signal parameters " << txParams);
294 Ptr<SpectrumSignalParameters> rxParams = txParams->Copy ();
295 rxParams->psd = Copy<SpectrumValue> (convertedTxPowerSpectrum);
296 Time delay = MicroSeconds (0);
297
298 Ptr<MobilityModel> receiverMobility = (*rxPhyIterator)->GetMobility ();
299
300 if (txMobility && receiverMobility)
301 {
302 double txAntennaGain = 0;
303 double rxAntennaGain = 0;
304 double propagationGainDb = 0;
305 double pathLossDb = 0;
306 if (rxParams->txAntenna != 0)
307 {
308 Angles txAngles (receiverMobility->GetPosition (), txMobility->GetPosition ());
309 txAntennaGain = rxParams->txAntenna->GetGainDb (txAngles);
310 NS_LOG_LOGIC ("txAntennaGain = " << txAntennaGain << " dB");
311 pathLossDb -= txAntennaGain;
312 }
313 Ptr<AntennaModel> rxAntenna = DynamicCast<AntennaModel>((*rxPhyIterator)->GetAntenna ());
314 if (rxAntenna != 0)
315 {
316 Angles rxAngles (txMobility->GetPosition (), receiverMobility->GetPosition ());
317 rxAntennaGain = rxAntenna->GetGainDb (rxAngles);
318 NS_LOG_LOGIC ("rxAntennaGain = " << rxAntennaGain << " dB");
319 pathLossDb -= rxAntennaGain;
320 }
322 {
323 propagationGainDb = m_propagationLoss->CalcRxPower (0, txMobility, receiverMobility);
324 NS_LOG_LOGIC ("propagationGainDb = " << propagationGainDb << " dB");
325 pathLossDb -= propagationGainDb;
326 }
327 NS_LOG_LOGIC ("total pathLoss = " << pathLossDb << " dB");
328 // Gain trace
329 m_gainTrace (txMobility, receiverMobility, txAntennaGain, rxAntennaGain, propagationGainDb, pathLossDb);
330 // Pathloss trace
331 m_pathLossTrace (txParams->txPhy, *rxPhyIterator, pathLossDb);
332 if (pathLossDb > m_maxLossDb)
333 {
334 // beyond range
335 continue;
336 }
337 double pathGainLinear = std::pow (10.0, (-pathLossDb) / 10.0);
338 *(rxParams->psd) *= pathGainLinear;
339
341 {
342 rxParams->psd = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity (rxParams->psd, txMobility, receiverMobility);
343 }
345 {
346 Ptr<const PhasedArrayModel> txPhasedArrayModel = DynamicCast<PhasedArrayModel> (txParams->txPhy->GetAntenna ());
347 Ptr<const PhasedArrayModel> rxPhasedArrayModel = DynamicCast<PhasedArrayModel> ((*rxPhyIterator)->GetAntenna ());
348
349 NS_ASSERT_MSG (txPhasedArrayModel && rxPhasedArrayModel, "PhasedArrayModel instances should be installed at both TX and RX SpectrumPhy in order to use PhasedArraySpectrumPropagationLoss.");
350
351 rxParams->psd = m_phasedArraySpectrumPropagationLoss->CalcRxPowerSpectralDensity (rxParams->psd, txMobility, receiverMobility, txPhasedArrayModel, rxPhasedArrayModel);
352 }
353
355 {
356 delay = m_propagationDelay->GetDelay (txMobility, receiverMobility);
357 }
358 }
359
360 if (rxNetDevice)
361 {
362 // the receiver has a NetDevice, so we expect that it is attached to a Node
363 uint32_t dstNode = rxNetDevice->GetNode ()->GetId ();
365 rxParams, *rxPhyIterator);
366 }
367 else
368 {
369 // the receiver is not attached to a NetDevice, so we cannot assume that it is attached to a node
371 rxParams, *rxPhyIterator);
372 }
373 }
374 }
375
376 }
377
378}
379
380void
382{
383 NS_LOG_FUNCTION (this);
384 receiver->StartRx (params);
385}
386
387std::size_t
389{
390 return m_numDevices;
391}
392
395{
397 // this method implementation is computationally intensive. This
398 // method would be faster if we actually used a std::vector for
399 // storing devices, which we don't due to the need to have fast
400 // SpectrumModel conversions and to allow PHY devices to change a
401 // SpectrumModel at run time. Note that having this method slow is
402 // acceptable as it is not used much at run time (often not at all).
403 // On the other hand, having slow SpectrumModel conversion would be
404 // less acceptable.
405 std::size_t j = 0;
406 for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
407 rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
408 ++rxInfoIterator)
409 {
410 for (const auto &phyIt : rxInfoIterator->second.m_rxPhys)
411 {
412 if (j == i)
413 {
414 return (*phyIt).GetDevice ();
415 }
416 j++;
417 }
418 }
419 NS_FATAL_ERROR ("m_numDevices > actual number of devices");
420 return 0;
421}
422
423} // 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.
virtual void RemoveRx(Ptr< SpectrumPhy > phy)
Remove a SpectrumPhy from a channel.
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.
virtual Ptr< Node > GetNode(void) const =0
uint32_t GetId(void) const
Definition: node.cc:109
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:556
static void ScheduleWithContext(uint32_t context, Time const &delay, FUNC f, Ts &&... args)
Schedule an event with the given context.
Definition: simulator.h:571
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.
Ptr< PhasedArraySpectrumPropagationLossModel > m_phasedArraySpectrumPropagationLoss
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:103
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:922
#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_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#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:1260
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139
phy
Definition: third.py:93