A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
multi-model-spectrum-channel.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 CTTC
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Nicola Baldo <nbaldo@cttc.es>
7 */
8
10
11#include "spectrum-converter.h"
12#include "spectrum-phy.h"
15#include "wraparound-model.h"
16
17#include "ns3/angles.h"
18#include "ns3/antenna-model.h"
19#include "ns3/double.h"
20#include "ns3/log.h"
21#include "ns3/mobility-model.h"
22#include "ns3/net-device.h"
23#include "ns3/node.h"
24#include "ns3/object.h"
25#include "ns3/packet-burst.h"
26#include "ns3/packet.h"
27#include "ns3/propagation-delay-model.h"
28#include "ns3/propagation-loss-model.h"
29#include "ns3/simulator.h"
30
31#include <algorithm>
32#include <iostream>
33#include <utility>
34
35namespace ns3
36{
37
38NS_LOG_COMPONENT_DEFINE("MultiModelSpectrumChannel");
39
41
42/**
43 * @brief Output stream operator
44 * @param lhs output stream
45 * @param rhs the TxSpectrumModelInfoMap to print
46 * @return an output stream
47 */
48std::ostream&
49operator<<(std::ostream& lhs, TxSpectrumModelInfoMap_t& rhs)
50{
51 for (auto it = rhs.begin(); it != rhs.end(); ++it)
52 {
53 for (auto jt = it->second.m_spectrumConverterMap.begin();
54 jt != it->second.m_spectrumConverterMap.end();
55 ++jt)
56 {
57 lhs << "(" << it->first << "," << jt->first << ") ";
58 }
59 }
60 return lhs;
61}
62
67
72
78
79void
87
90{
91 static TypeId tid = TypeId("ns3::MultiModelSpectrumChannel")
93 .SetGroupName("Spectrum")
94 .AddConstructor<MultiModelSpectrumChannel>()
95
96 ;
97 return tid;
98}
99
100void
102{
103 NS_LOG_FUNCTION(this << phy);
104
105 // remove a previous entry of this phy if it exists
106 // we need to scan for all rxSpectrumModel values since we don't
107 // know which spectrum model the phy had when it was previously added
108 // (it's probably different than the current one)
109 for (auto rxInfoIterator = m_rxSpectrumModelInfoMap.begin();
110 rxInfoIterator != m_rxSpectrumModelInfoMap.end();
111 ++rxInfoIterator)
112 {
113 auto phyIt = std::find(rxInfoIterator->second.m_rxPhys.begin(),
114 rxInfoIterator->second.m_rxPhys.end(),
115 phy);
116 if (phyIt != rxInfoIterator->second.m_rxPhys.end())
117 {
118 rxInfoIterator->second.m_rxPhys.erase(phyIt);
119 --m_numDevices;
120 break; // there should be at most one entry
121 }
122 }
123}
124
125void
127{
128 NS_LOG_FUNCTION(this << phy);
129
130 Ptr<const SpectrumModel> rxSpectrumModel = phy->GetRxSpectrumModel();
131
132 NS_ASSERT_MSG(rxSpectrumModel,
133 "phy->GetRxSpectrumModel () returned 0. Please check that the RxSpectrumModel is "
134 "already set for the phy before calling MultiModelSpectrumChannel::AddRx (phy)");
135
136 const auto rxSpectrumModelUid = rxSpectrumModel->GetUid();
137
138 RemoveRx(phy);
139
140 ++m_numDevices;
141
142 auto [rxInfoIterator, inserted] =
143 m_rxSpectrumModelInfoMap.emplace(rxSpectrumModelUid, RxSpectrumModelInfo(rxSpectrumModel));
144
145 // rxInfoIterator points either to the newly inserted element or to the element that
146 // prevented insertion. In both cases, add the phy to the element pointed to by rxInfoIterator
147 rxInfoIterator->second.m_rxPhys.push_back(phy);
148
149 if (inserted)
150 {
151 // create the necessary converters for all the TX spectrum models that we know of
152 for (auto txInfoIterator = m_txSpectrumModelInfoMap.begin();
153 txInfoIterator != m_txSpectrumModelInfoMap.end();
154 ++txInfoIterator)
155 {
156 auto txSpectrumModel = txInfoIterator->second.m_txSpectrumModel;
157 const auto txSpectrumModelUid = txSpectrumModel->GetUid();
158
159 if (rxSpectrumModelUid != txSpectrumModelUid &&
160 !txSpectrumModel->IsOrthogonal(*rxSpectrumModel))
161 {
162 NS_LOG_LOGIC("Creating converter between SpectrumModelUid "
163 << txSpectrumModel->GetUid() << " and " << rxSpectrumModelUid);
164 SpectrumConverter converter(txSpectrumModel, rxSpectrumModel);
165 auto ret2 = txInfoIterator->second.m_spectrumConverterMap.insert(
166 std::make_pair(rxSpectrumModelUid, converter));
167 NS_ASSERT(ret2.second);
168 }
169 }
170 }
171}
172
173TxSpectrumModelInfoMap_t::const_iterator
175 Ptr<const SpectrumModel> txSpectrumModel)
176{
177 NS_LOG_FUNCTION(this << txSpectrumModel);
178 const auto txSpectrumModelUid = txSpectrumModel->GetUid();
179 auto 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 auto ret = m_txSpectrumModelInfoMap.insert(
186 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 (auto rxInfoIterator = m_rxSpectrumModelInfoMap.begin();
192 rxInfoIterator != m_rxSpectrumModelInfoMap.end();
193 ++rxInfoIterator)
194 {
195 auto rxSpectrumModel = rxInfoIterator->second.m_rxSpectrumModel;
196 const auto rxSpectrumModelUid = rxSpectrumModel->GetUid();
197
198 if (rxSpectrumModelUid != txSpectrumModelUid &&
199 !txSpectrumModel->IsOrthogonal(*rxSpectrumModel))
200 {
201 NS_LOG_LOGIC("Creating converter between SpectrumModelUid "
202 << txSpectrumModelUid << " and " << rxSpectrumModelUid);
203
204 SpectrumConverter converter(txSpectrumModel, rxSpectrumModel);
205 auto ret2 = txInfoIterator->second.m_spectrumConverterMap.insert(
206 std::make_pair(rxSpectrumModelUid, converter));
207 NS_ASSERT(ret2.second);
208 }
209 }
210 }
211 else
212 {
213 NS_LOG_LOGIC("SpectrumModelUid " << txSpectrumModelUid << " already present");
214 }
215 return txInfoIterator;
216}
217
218void
220{
221 NS_LOG_FUNCTION(this << txParams);
222
223 NS_ASSERT(txParams->txPhy);
224 NS_ASSERT(txParams->psd);
225 auto txParamsTrace = txParams->Copy(); // copy it since traced value cannot be const (because of
226 // potential underlying DynamicCasts)
227 m_txSigParamsTrace(txParamsTrace);
228
229 auto wraparound = GetObject<WraparoundModel>();
230 auto refTxMobility = txParams->txPhy->GetMobility();
231 auto txMobility = refTxMobility;
232 const auto txSpectrumModelUid = txParams->psd->GetSpectrumModelUid();
233 NS_LOG_LOGIC("txSpectrumModelUid " << txSpectrumModelUid);
234
235 const auto txInfoIterator =
236 FindAndEventuallyAddTxSpectrumModel(txParams->psd->GetSpectrumModel());
237 NS_ASSERT(txInfoIterator != m_txSpectrumModelInfoMap.cend());
238
239 NS_LOG_LOGIC("converter map for TX SpectrumModel with Uid " << txInfoIterator->first);
240 NS_LOG_LOGIC("converter map size: " << txInfoIterator->second.m_spectrumConverterMap.size());
241 NS_LOG_LOGIC("converter map first element: "
242 << txInfoIterator->second.m_spectrumConverterMap.begin()->first);
243
244 std::map<SpectrumModelUid_t, Ptr<SpectrumValue>> convertedPsds{};
245 for (auto rxInfoIterator = m_rxSpectrumModelInfoMap.begin();
246 rxInfoIterator != m_rxSpectrumModelInfoMap.end();
247 ++rxInfoIterator)
248 {
249 if (rxInfoIterator->second.m_rxPhys.empty())
250 {
251 continue;
252 }
253 const auto 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 "
265 << txSpectrumModelUid << " --> " << rxSpectrumModelUid);
266 if (auto rxConverterIterator =
267 txInfoIterator->second.m_spectrumConverterMap.find(rxSpectrumModelUid);
268 rxConverterIterator == txInfoIterator->second.m_spectrumConverterMap.end())
269 {
270 // No converter means TX SpectrumModel is orthogonal to RX SpectrumModel
271 continue;
272 }
273 else
274 {
275 convertedTxPowerSpectrum = rxConverterIterator->second.Convert(txParams->psd);
276 }
277 }
278 convertedPsds.emplace(rxSpectrumModelUid, convertedTxPowerSpectrum);
279 }
280
281 for (auto rxInfoIterator = m_rxSpectrumModelInfoMap.begin();
282 rxInfoIterator != m_rxSpectrumModelInfoMap.end();
283 ++rxInfoIterator)
284 {
285 if (rxInfoIterator->second.m_rxPhys.empty())
286 {
287 continue;
288 }
289
290 const auto rxSpectrumModelUid = rxInfoIterator->second.m_rxSpectrumModel->GetUid();
291
292 if (const auto IsOrthogonal = rxInfoIterator->second.m_rxSpectrumModel->IsOrthogonal(
293 *txInfoIterator->second.m_txSpectrumModel);
294 (txSpectrumModelUid != rxSpectrumModelUid) &&
295 !txInfoIterator->second.m_spectrumConverterMap.contains(rxSpectrumModelUid) &&
296 IsOrthogonal)
297 {
298 // TX SpectrumModel is orthogonal to RX SpectrumModel
299 continue;
300 }
301
302 for (auto rxPhyIterator = rxInfoIterator->second.m_rxPhys.begin();
303 rxPhyIterator != rxInfoIterator->second.m_rxPhys.end();
304 ++rxPhyIterator)
305 {
306 NS_ASSERT_MSG((*rxPhyIterator)->GetRxSpectrumModel()->GetUid() == rxSpectrumModelUid,
307 "SpectrumModel change was not notified to MultiModelSpectrumChannel "
308 "(i.e., AddRx should be called again after model is changed)");
309
310 auto txAntennaGain{0.0};
311 if ((*rxPhyIterator) != txParams->txPhy)
312 {
313 auto rxNetDevice = (*rxPhyIterator)->GetDevice();
314 auto txNetDevice = txParams->txPhy->GetDevice();
315
316 if (rxNetDevice && txNetDevice)
317 {
318 // we assume that devices are attached to a node
319 if (rxNetDevice->GetNode()->GetId() == txNetDevice->GetNode()->GetId())
320 {
322 "Skipping the pathloss calculation among different antennas of the "
323 "same node, not supported yet by any pathloss model in ns-3.");
324 continue;
325 }
326 }
327
328 if (m_filter && m_filter->Filter(txParams, *rxPhyIterator))
329 {
330 continue;
331 }
332
333 NS_LOG_LOGIC("copying signal parameters " << txParams);
334 auto rxParams = txParams->Copy();
335 rxParams->psd = Copy<SpectrumValue>(convertedPsds.at(rxSpectrumModelUid));
336 Time delay{0};
337
338 if (rxParams->precodingMatrix &&
339 (rxParams->precodingMatrix->GetNumPages() != rxParams->psd->GetValuesN()))
340 {
341 NS_LOG_WARN("Precoding matrix conversion not supported yet.");
342 rxParams->precodingMatrix = nullptr;
343 }
344
345 auto receiverMobility = (*rxPhyIterator)->GetMobility();
346
347 if (txMobility && receiverMobility)
348 {
349 if (wraparound)
350 {
351 // Use virtual mobility model instead
352 txMobility =
353 wraparound->GetVirtualMobilityModel(refTxMobility, receiverMobility);
354 }
355 rxParams->txMobility = txMobility;
356
357 if (rxParams->txAntenna)
358 {
359 Angles txAngles(receiverMobility->GetPosition(), txMobility->GetPosition());
360 txAntennaGain = rxParams->txAntenna->GetGainDb(txAngles);
361 NS_LOG_LOGIC("txAntennaGain = " << txAntennaGain << " dB");
362 }
364 {
365 delay = m_propagationDelay->GetDelay(txMobility, receiverMobility);
366 }
367 }
368
369 RxInfo rxInfo{.txPsd = txParams->psd,
370 .txAntennaGain = txAntennaGain,
371 .params = rxParams,
372 .receiver = *rxPhyIterator,
373 .availableConvertedPsds = convertedPsds};
374 if (rxNetDevice)
375 {
376 // the receiver has a NetDevice, so we expect that it is attached to a Node
377 auto dstNode = rxNetDevice->GetNode()->GetId();
379 delay,
381 this,
382 rxInfo);
383 }
384 else
385 {
386 // the receiver is not attached to a NetDevice, so we cannot assume that it is
387 // attached to a node
389 }
390 }
391 }
392 }
393}
394
395void
397{
398 NS_LOG_FUNCTION(this);
399
400 auto rxParams{rxInfo.params};
401 const auto rxSpectrumModelUid = rxParams->psd->GetSpectrumModelUid();
402 const auto phySpectrumModelUid = rxInfo.receiver->GetRxSpectrumModel()->GetUid();
403 NS_LOG_LOGIC("rxSpectrumModelUid " << rxSpectrumModelUid << " phySpectrumModelUid "
404 << phySpectrumModelUid);
405
406 if (rxSpectrumModelUid != phySpectrumModelUid)
407 {
408 NS_LOG_LOGIC("SpectrumModelUid changed since TX started");
409
410 const auto itConvertedPsd = rxInfo.availableConvertedPsds.find(phySpectrumModelUid);
411 if (itConvertedPsd != rxInfo.availableConvertedPsds.cend())
412 {
413 NS_LOG_LOGIC("converted PSD already exists for " << phySpectrumModelUid);
414 rxParams->psd = itConvertedPsd->second;
415 }
416 else
417 {
418 const auto txInfoIterator =
419 FindAndEventuallyAddTxSpectrumModel(rxInfo.txPsd->GetSpectrumModel());
420 NS_ASSERT(txInfoIterator != m_txSpectrumModelInfoMap.cend());
421
422 const auto txSpectrumModelUid = rxInfo.txPsd->GetSpectrumModelUid();
423 NS_LOG_LOGIC("converting txPowerSpectrum SpectrumModelUids "
424 << txSpectrumModelUid << " --> " << phySpectrumModelUid);
425 if (const auto rxConverterIterator =
426 txInfoIterator->second.m_spectrumConverterMap.find(phySpectrumModelUid);
427 rxConverterIterator == txInfoIterator->second.m_spectrumConverterMap.end())
428 {
429 // No converter means TX SpectrumModel is orthogonal to current PHY SpectrumModel
430 return;
431 }
432 else
433 {
434 rxParams->psd = rxConverterIterator->second.Convert(rxInfo.txPsd);
435 }
436 }
437 }
438
439 auto txMobility = rxParams->txMobility;
440 auto rxMobility = rxInfo.receiver->GetMobility();
441 if (txMobility && rxMobility)
442 {
443 auto pathLossDb{-rxInfo.txAntennaGain};
444 auto rxAntennaGain{0.0};
445 auto propagationGainDb{0.0};
446
447 if (auto rxAntenna = DynamicCast<AntennaModel>(rxInfo.receiver->GetAntenna()))
448 {
449 Angles rxAngles(txMobility->GetPosition(), rxMobility->GetPosition());
450 rxAntennaGain = rxAntenna->GetGainDb(rxAngles);
451 NS_LOG_LOGIC("rxAntennaGain = " << rxAntennaGain << " dB");
452 pathLossDb -= rxAntennaGain;
453 }
454
455 if (m_propagationLoss && (txMobility->GetPosition() != rxMobility->GetPosition()))
456 {
457 propagationGainDb = m_propagationLoss->CalcRxPower(0, txMobility, rxMobility);
458 NS_LOG_LOGIC("propagationGainDb = " << propagationGainDb << " dB");
459 pathLossDb -= propagationGainDb;
460 }
461
462 NS_LOG_LOGIC("total pathLoss = " << pathLossDb << " dB");
463
464 // Gain trace
465 m_gainTrace(txMobility,
466 rxMobility,
467 rxInfo.txAntennaGain,
468 rxAntennaGain,
469 propagationGainDb,
470 pathLossDb);
471
472 // Pathloss trace
473 m_pathLossTrace(rxParams->txPhy, rxInfo.receiver, pathLossDb);
474
475 if (pathLossDb > m_maxLossDb)
476 {
477 // beyond range
478 return;
479 }
480
481 const auto pathLossLinear = std::pow(10.0, (-pathLossDb) / 10.0);
482 *(rxParams->psd) *= pathLossLinear;
483
485 {
486 rxParams->psd = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity(rxParams,
487 txMobility,
488 rxMobility);
489 }
491 {
492 auto txPhasedArrayModel = DynamicCast<PhasedArrayModel>(rxParams->txPhy->GetAntenna());
493 auto rxPhasedArrayModel = DynamicCast<PhasedArrayModel>(rxInfo.receiver->GetAntenna());
494
495 NS_ASSERT_MSG(txPhasedArrayModel && rxPhasedArrayModel,
496 "PhasedArrayModel instances should be installed at both TX and RX "
497 "SpectrumPhy in order to use PhasedArraySpectrumPropagationLoss.");
498
499 rxParams = m_phasedArraySpectrumPropagationLoss->CalcRxPowerSpectralDensity(
500 rxParams,
501 txMobility,
502 rxMobility,
503 txPhasedArrayModel,
504 rxPhasedArrayModel);
505 }
506 }
507
508 rxInfo.receiver->StartRx(rxParams);
509}
510
511std::size_t
516
519{
521 // this method implementation is computationally intensive. This
522 // method would be faster if we actually used a std::vector for
523 // storing devices, which we don't due to the need to have fast
524 // SpectrumModel conversions and to allow PHY devices to change a
525 // SpectrumModel at run time. Note that having this method slow is
526 // acceptable as it is not used much at run time (often not at all).
527 // On the other hand, having slow SpectrumModel conversion would be
528 // less acceptable.
529 std::size_t j = 0;
530 for (auto rxInfoIterator = m_rxSpectrumModelInfoMap.begin();
531 rxInfoIterator != m_rxSpectrumModelInfoMap.end();
532 ++rxInfoIterator)
533 {
534 for (const auto& phyIt : rxInfoIterator->second.m_rxPhys)
535 {
536 if (j == i)
537 {
538 return (*phyIt).GetDevice();
539 }
540 j++;
541 }
542 }
543 NS_FATAL_ERROR("m_numDevices > actual number of devices");
544 return nullptr;
545}
546
547} // namespace ns3
Class holding the azimuth and inclination angles of spherical coordinates.
Definition angles.h:107
This SpectrumChannel implementation can handle the presence of SpectrumPhy instances which can use di...
void RemoveRx(Ptr< SpectrumPhy > phy) override
Remove a SpectrumPhy from a channel.
Ptr< NetDevice > GetDevice(std::size_t i) const override
virtual void StartRx(const RxInfo &rxInfo)
Used internally to reschedule transmission after the propagation delay.
void AddRx(Ptr< SpectrumPhy > phy) override
Add a SpectrumPhy to a channel, so it can receive packets.
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.
void DoDispose() override
Destructor implementation.
void StartTx(Ptr< SpectrumSignalParameters > params) override
Used by attached PHY instances to transmit signals on the channel.
TxSpectrumModelInfoMap_t::const_iterator FindAndEventuallyAddTxSpectrumModel(Ptr< const SpectrumModel > txSpectrumModel)
This method checks if m_rxSpectrumModelInfoMap contains an entry for the given TX SpectrumModel.
static TypeId GetTypeId()
Get the type ID.
RxSpectrumModelInfoMap_t m_rxSpectrumModelInfoMap
Data structure holding, for each RX spectrum model, all the corresponding SpectrumPhy instances.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:518
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
The Rx spectrum model information.
RxSpectrumModelInfo(Ptr< const SpectrumModel > rxSpectrumModel)
Constructor.
Ptr< const SpectrumModel > m_rxSpectrumModel
Rx Spectrum model.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static void ScheduleWithContext(uint32_t context, const Time &delay, FUNC f, Ts &&... args)
Schedule an event with the given context.
Definition simulator.h:597
TracedCallback< Ptr< SpectrumSignalParameters > > m_txSigParamsTrace
Traced callback for SpectrumSignalParameters in StartTx requests.
void DoDispose() override
Destructor implementation.
Ptr< SpectrumTransmitFilter > m_filter
Transmit filter to be used with this channel.
Ptr< PropagationDelayModel > m_propagationDelay
Propagation delay model to be used with this channel.
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 SpectrumPhy >, Ptr< const SpectrumPhy >, double > m_pathLossTrace
The PathLoss trace source.
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...
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
The Tx spectrum model information.
Ptr< const SpectrumModel > m_txSpectrumModel
Tx Spectrum model.
TxSpectrumModelInfo(Ptr< const SpectrumModel > txSpectrumModel)
Constructor.
a unique identifier for an interface.
Definition type-id.h:50
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#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:75
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:274
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:253
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
std::map< SpectrumModelUid_t, TxSpectrumModelInfo > TxSpectrumModelInfoMap_t
Container: SpectrumModelUid_t, TxSpectrumModelInfo.
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:148
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:643
Ptr< T > Copy(Ptr< T > object)
Return a deep copy of a Ptr.
Definition ptr.h:667
Structure that stores the parameters needed to handle the reception of a signal by a given receiver.
Ptr< SpectrumPhy > receiver
pointer to the receiver SpectrumPhy
double txAntennaGain
antenna gain at the transmitter
Ptr< SpectrumSignalParameters > params
signal parameters
std::map< SpectrumModelUid_t, Ptr< SpectrumValue > > availableConvertedPsds
available converted PSDs from the TX PSD