17#include "ns3/angles.h"
18#include "ns3/antenna-model.h"
19#include "ns3/double.h"
21#include "ns3/mobility-model.h"
22#include "ns3/net-device.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"
51 for (
auto it = rhs.begin(); it != rhs.end(); ++it)
53 for (
auto jt = it->second.m_spectrumConverterMap.begin();
54 jt != it->second.m_spectrumConverterMap.end();
57 lhs <<
"(" << it->first <<
"," << jt->first <<
") ";
91 static TypeId tid =
TypeId(
"ns3::MultiModelSpectrumChannel")
93 .SetGroupName(
"Spectrum")
113 auto phyIt = std::find(rxInfoIterator->second.m_rxPhys.begin(),
114 rxInfoIterator->second.m_rxPhys.end(),
116 if (phyIt != rxInfoIterator->second.m_rxPhys.end())
118 rxInfoIterator->second.m_rxPhys.erase(phyIt);
133 "phy->GetRxSpectrumModel () returned 0. Please check that the RxSpectrumModel is "
134 "already set for the phy before calling MultiModelSpectrumChannel::AddRx (phy)");
136 const auto rxSpectrumModelUid = rxSpectrumModel->GetUid();
142 auto [rxInfoIterator, inserted] =
147 rxInfoIterator->second.m_rxPhys.push_back(phy);
156 auto txSpectrumModel = txInfoIterator->second.m_txSpectrumModel;
157 const auto txSpectrumModelUid = txSpectrumModel->GetUid();
159 if (rxSpectrumModelUid != txSpectrumModelUid &&
160 !txSpectrumModel->IsOrthogonal(*rxSpectrumModel))
162 NS_LOG_LOGIC(
"Creating converter between SpectrumModelUid "
163 << txSpectrumModel->GetUid() <<
" and " << rxSpectrumModelUid);
165 auto ret2 = txInfoIterator->second.m_spectrumConverterMap.insert(
166 std::make_pair(rxSpectrumModelUid, converter));
173TxSpectrumModelInfoMap_t::const_iterator
178 const auto txSpectrumModelUid = txSpectrumModel->GetUid();
188 txInfoIterator = ret.first;
195 auto rxSpectrumModel = rxInfoIterator->second.m_rxSpectrumModel;
196 const auto rxSpectrumModelUid = rxSpectrumModel->GetUid();
198 if (rxSpectrumModelUid != txSpectrumModelUid &&
199 !txSpectrumModel->IsOrthogonal(*rxSpectrumModel))
201 NS_LOG_LOGIC(
"Creating converter between SpectrumModelUid "
202 << txSpectrumModelUid <<
" and " << rxSpectrumModelUid);
205 auto ret2 = txInfoIterator->second.m_spectrumConverterMap.insert(
206 std::make_pair(rxSpectrumModelUid, converter));
213 NS_LOG_LOGIC(
"SpectrumModelUid " << txSpectrumModelUid <<
" already present");
215 return txInfoIterator;
225 auto txParamsTrace = txParams->Copy();
230 auto refTxMobility = txParams->txPhy->GetMobility();
231 auto txMobility = refTxMobility;
232 const auto txSpectrumModelUid = txParams->psd->GetSpectrumModelUid();
233 NS_LOG_LOGIC(
"txSpectrumModelUid " << txSpectrumModelUid);
235 const auto txInfoIterator =
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());
242 << txInfoIterator->second.m_spectrumConverterMap.begin()->first);
244 std::map<SpectrumModelUid_t, Ptr<SpectrumValue>> convertedPsds{};
249 if (rxInfoIterator->second.m_rxPhys.empty())
253 const auto rxSpectrumModelUid = rxInfoIterator->second.m_rxSpectrumModel->GetUid();
254 NS_LOG_LOGIC(
"rxSpectrumModelUids " << rxSpectrumModelUid);
257 if (txSpectrumModelUid == rxSpectrumModelUid)
260 convertedTxPowerSpectrum = txParams->psd;
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())
275 convertedTxPowerSpectrum = rxConverterIterator->second.Convert(txParams->psd);
278 convertedPsds.emplace(rxSpectrumModelUid, convertedTxPowerSpectrum);
285 if (rxInfoIterator->second.m_rxPhys.empty())
290 const auto rxSpectrumModelUid = rxInfoIterator->second.m_rxSpectrumModel->GetUid();
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) &&
302 for (
auto rxPhyIterator = rxInfoIterator->second.m_rxPhys.begin();
303 rxPhyIterator != rxInfoIterator->second.m_rxPhys.end();
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)");
310 auto txAntennaGain{0.0};
311 if ((*rxPhyIterator) != txParams->txPhy)
313 auto rxNetDevice = (*rxPhyIterator)->GetDevice();
314 auto txNetDevice = txParams->txPhy->GetDevice();
316 if (rxNetDevice && txNetDevice)
319 if (rxNetDevice->GetNode()->GetId() == txNetDevice->GetNode()->GetId())
322 "Skipping the pathloss calculation among different antennas of the "
323 "same node, not supported yet by any pathloss model in ns-3.");
334 auto rxParams = txParams->Copy();
338 if (rxParams->precodingMatrix &&
339 (rxParams->precodingMatrix->GetNumPages() != rxParams->psd->GetValuesN()))
341 NS_LOG_WARN(
"Precoding matrix conversion not supported yet.");
342 rxParams->precodingMatrix =
nullptr;
345 auto receiverMobility = (*rxPhyIterator)->GetMobility();
347 if (txMobility && receiverMobility)
353 wraparound->GetVirtualMobilityModel(refTxMobility, receiverMobility);
355 rxParams->txMobility = txMobility;
357 if (rxParams->txAntenna)
359 Angles txAngles(receiverMobility->GetPosition(), txMobility->GetPosition());
360 txAntennaGain = rxParams->txAntenna->GetGainDb(txAngles);
361 NS_LOG_LOGIC(
"txAntennaGain = " << txAntennaGain <<
" dB");
369 RxInfo rxInfo{.txPsd = txParams->psd,
370 .txAntennaGain = txAntennaGain,
372 .receiver = *rxPhyIterator,
373 .availableConvertedPsds = convertedPsds};
377 auto dstNode = rxNetDevice->GetNode()->GetId();
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);
406 if (rxSpectrumModelUid != phySpectrumModelUid)
408 NS_LOG_LOGIC(
"SpectrumModelUid changed since TX started");
413 NS_LOG_LOGIC(
"converted PSD already exists for " << phySpectrumModelUid);
414 rxParams->psd = itConvertedPsd->second;
418 const auto txInfoIterator =
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())
434 rxParams->psd = rxConverterIterator->second.Convert(rxInfo.
txPsd);
439 auto txMobility = rxParams->txMobility;
440 auto rxMobility = rxInfo.
receiver->GetMobility();
441 if (txMobility && rxMobility)
444 auto rxAntennaGain{0.0};
445 auto propagationGainDb{0.0};
449 Angles rxAngles(txMobility->GetPosition(), rxMobility->GetPosition());
450 rxAntennaGain = rxAntenna->GetGainDb(rxAngles);
451 NS_LOG_LOGIC(
"rxAntennaGain = " << rxAntennaGain <<
" dB");
452 pathLossDb -= rxAntennaGain;
455 if (
m_propagationLoss && (txMobility->GetPosition() != rxMobility->GetPosition()))
458 NS_LOG_LOGIC(
"propagationGainDb = " << propagationGainDb <<
" dB");
459 pathLossDb -= propagationGainDb;
462 NS_LOG_LOGIC(
"total pathLoss = " << pathLossDb <<
" dB");
481 const auto pathLossLinear = std::pow(10.0, (-pathLossDb) / 10.0);
482 *(rxParams->psd) *= pathLossLinear;
496 "PhasedArrayModel instances should be installed at both TX and RX "
497 "SpectrumPhy in order to use PhasedArraySpectrumPropagationLoss.");
534 for (
const auto& phyIt : rxInfoIterator->second.m_rxPhys)
538 return (*phyIt).GetDevice();
Class holding the azimuth and inclination angles of spherical coordinates.
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
std::size_t GetNDevices() 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.
MultiModelSpectrumChannel()
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.
Smart pointer class similar to boost::intrusive_ptr.
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.
static void ScheduleWithContext(uint32_t context, const Time &delay, FUNC f, Ts &&... args)
Schedule an event with the given context.
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.
SpectrumChannel()
constructor
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.
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.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#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.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
#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.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
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)
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Ptr< T > Copy(Ptr< T > object)
Return a deep copy of a Ptr.
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
Ptr< SpectrumValue > txPsd
transmitted PSD
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