5#include "realistic-beamforming-algorithm.h"
8#include "nr-mac-scheduler-ns3.h"
12#include "ns3/double.h"
13#include "ns3/mobility-model.h"
15#include "ns3/nr-spectrum-value-helper.h"
16#include "ns3/random-variable-stream.h"
17#include "ns3/three-gpp-spectrum-propagation-loss-model.h"
18#include "ns3/uinteger.h"
23NS_LOG_COMPONENT_DEFINE(
"RealisticBeamformingAlgorithm");
24NS_OBJECT_ENSURE_REGISTERED(RealisticBeamformingAlgorithm);
28 m_normalRandomVariable = CreateObject<NormalRandomVariable>();
32RealisticBeamformingAlgorithm::Install(
const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
33 const Ptr<NrSpectrumPhy>& ueSpectrumPhy,
34 const Ptr<NrMacScheduler>& scheduler)
36 NS_LOG_FUNCTION(
this);
37 m_gnbSpectrumPhy = gnbSpectrumPhy;
38 m_ueSpectrumPhy = ueSpectrumPhy;
39 m_scheduler = scheduler;
40 m_nrUePhy = DynamicCast<NrUePhy>(m_ueSpectrumPhy->GetPhy());
46 NS_LOG_FUNCTION(
this << stream);
47 m_normalRandomVariable->SetStream(stream);
52RealisticBeamformingAlgorithm::DoDispose()
54 m_gnbDevice =
nullptr;
56 m_gnbSpectrumPhy =
nullptr;
57 m_ueSpectrumPhy =
nullptr;
58 m_scheduler =
nullptr;
66 TypeId(
"ns3::RealisticBeamformingAlgorithm")
68 .AddConstructor<RealisticBeamformingAlgorithm>()
71 "Samples per antenna row/column",
73 MakeUintegerAccessor(&RealisticBeamformingAlgorithm::m_oversamplingFactor),
74 MakeUintegerChecker<uint8_t>(1, 4))
75 .AddAttribute(
"UseSnrSrs",
76 "Denotes whether the SRS measurement will be SNR or SINR. If False"
77 "SINR is used, if True the SNR",
79 MakeBooleanAccessor(&RealisticBeamformingAlgorithm::SetUseSnrSrs,
80 &RealisticBeamformingAlgorithm::UseSnrSrs),
81 MakeBooleanChecker());
86RealisticBeamformingAlgorithm::GetSrsSymbolsPerSlot()
88 NS_LOG_FUNCTION(
this);
89 NS_ABORT_MSG_UNLESS(m_scheduler,
"Scheduler for the given ccId does not exist!");
90 return (DynamicCast<NrMacSchedulerNs3>(m_scheduler))->GetSrsCtrlSyms();
93RealisticBeamformingAlgorithm::TriggerEventConf
94RealisticBeamformingAlgorithm::GetTriggerEventConf()
const
96 NS_LOG_FUNCTION(
this);
97 NS_ABORT_MSG_UNLESS(m_gnbSpectrumPhy,
"gNB spectrum PHY for the given ccId does not exist!");
98 Ptr<RealisticBfManager> realBf =
99 DynamicCast<RealisticBfManager>(m_gnbSpectrumPhy->GetBeamManager());
102 "Realistic BF manager at gNB does not exist. Realistic BF manager at gNB should "
103 "be installed when using realistic BF algorithm.");
105 TriggerEventConf conf;
106 conf.event = realBf->GetTriggerEvent();
107 conf.updatePeriodicity = realBf->GetUpdatePeriodicity();
108 conf.updateDelay = realBf->GetUpdateDelay();
113RealisticBeamformingAlgorithm::SetUseSnrSrs(
bool v)
119RealisticBeamformingAlgorithm::UseSnrSrs()
const
127 NS_LOG_FUNCTION(
this);
137 NS_LOG_FUNCTION(
this);
147 NS_LOG_FUNCTION(
this);
148 NS_ABORT_MSG_UNLESS(m_gnbSpectrumPhy && m_ueSpectrumPhy,
149 "Function install must be called to install gNB and UE pair");
150 if (m_nrUePhy->GetRnti() != rnti)
152 NS_LOG_INFO(
"Ignoring SRS report. Not for me. Report for RNTI:"
153 << rnti <<
", and my RNTI is:" << m_nrUePhy->GetRnti());
157 m_srsSymbolsCounter++;
160 m_maxSrsSinrPerSlot =
161 (m_srsSymbolsCounter > 1) ? std::max(srsReport, m_maxSrsSinrPerSlot) : srsReport;
164 if (m_srsSymbolsCounter == GetSrsSymbolsPerSlot())
167 m_srsSymbolsCounter = 0;
171 if (conf.event == RealisticBfManager::SRS_COUNT)
174 m_srsPeriodicityCounter++;
176 if (m_srsPeriodicityCounter == conf.updatePeriodicity)
178 NS_LOG_INFO(
"Update periodicity for updating BF reached. Time to trigger realistic "
179 "BF helper callback.");
181 Simulator::ScheduleNow(&RealisticBeamformingAlgorithm::NotifyHelper,
this);
183 m_srsPeriodicityCounter = 0;
186 else if (conf.event == RealisticBfManager::DELAYED_UPDATE)
188 NS_LOG_INFO(
"Received all SRS symbols per current slot. Scheduler realistic BF helper "
191 dui.
updateTime = Simulator::Now() + conf.updateDelay;
192 dui.
srsSinr = m_maxSrsSinrPerSlot;
194 m_delayedUpdateInfo.push(dui);
196 Simulator::Schedule(conf.updateDelay,
197 &RealisticBeamformingAlgorithm::NotifyHelper,
199 Simulator::Schedule(conf.updateDelay + NanoSeconds(1),
200 &RealisticBeamformingAlgorithm::RemoveUsedDelayedUpdateInfo,
207 NS_ABORT_MSG(
"Unknown trigger event type.");
213RealisticBeamformingAlgorithm::RemoveUsedDelayedUpdateInfo()
215 NS_LOG_FUNCTION(
this);
216 NS_ASSERT_MSG(!m_delayedUpdateInfo.empty(),
" No elements in m_delayedUpdateInfo queue.");
217 m_delayedUpdateInfo.pop();
221RealisticBeamformingAlgorithm::NotifyHelper()
223 NS_LOG_FUNCTION(
this);
224 m_helperCallback(m_gnbSpectrumPhy, m_ueSpectrumPhy);
228RealisticBeamformingAlgorithm::SetTriggerCallback(RealisticBfHelperCallback callback)
230 m_helperCallback = callback;
233Ptr<const MatrixBasedChannelModel::ChannelMatrix>
234RealisticBeamformingAlgorithm::GetChannelMatrix()
const
236 NS_LOG_FUNCTION(
this);
237 Ptr<SpectrumChannel> gnbSpectrumChannel =
239 ->GetSpectrumChannel();
241 Ptr<SpectrumChannel> ueSpectrumChannel = m_ueSpectrumPhy->GetSpectrumChannel();
243 Ptr<PhasedArraySpectrumPropagationLossModel> gnbThreeGppSpectrumPropModel =
244 gnbSpectrumChannel->GetPhasedArraySpectrumPropagationLossModel();
245 Ptr<ThreeGppSpectrumPropagationLossModel> threeGppSplm =
246 DynamicCast<ThreeGppSpectrumPropagationLossModel>(gnbThreeGppSpectrumPropModel);
247 Ptr<MatrixBasedChannelModel> matrixBasedChannelModel = threeGppSplm->GetChannelModel();
248 Ptr<ThreeGppChannelModel> channelModel =
249 DynamicCast<ThreeGppChannelModel>(matrixBasedChannelModel);
251 NS_ASSERT(channelModel !=
nullptr);
253 Ptr<const MatrixBasedChannelModel::ChannelMatrix> originalChannelMatrix =
254 channelModel->GetChannel(m_gnbSpectrumPhy->GetMobility(),
255 m_ueSpectrumPhy->GetMobility(),
256 m_gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>(),
257 m_ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>());
259 Ptr<const MatrixBasedChannelModel::ChannelMatrix> channelMatrixCopy =
260 Copy<const MatrixBasedChannelModel::ChannelMatrix>(originalChannelMatrix);
261 return channelMatrixCopy;
267 NS_ABORT_MSG_IF(m_gnbSpectrumPhy ==
nullptr || m_ueSpectrumPhy ==
nullptr,
268 "Gnb or UE PHY layer not set.");
270 m_gnbSpectrumPhy->GetMobility()->GetDistanceFrom(m_ueSpectrumPhy->GetMobility());
271 NS_ABORT_MSG_IF(distance == 0,
272 "Beamforming method cannot be performed between two devices that are placed in "
273 "the same position.");
276 double maxTxTheta = 0;
277 double maxRxTheta = 0;
278 uint16_t maxTxSector = 0;
279 uint16_t maxRxSector = 0;
280 PhasedArrayModel::ComplexVector maxTxW;
281 PhasedArrayModel::ComplexVector maxRxW;
285 Ptr<const MatrixBasedChannelModel::ChannelMatrix> channelMatrix =
nullptr;
287 if (conf.event == RealisticBfManager::DELAYED_UPDATE)
289 NS_ASSERT(!m_delayedUpdateInfo.empty());
291 NS_ABORT_MSG_UNLESS(dui.
updateTime == Simulator::Now(),
292 "Current time should be equal to the updateTime from the "
293 "DelayedUpdateInfo structure.");
300 srsSinr = m_maxSrsSinrPerSlot;
301 channelMatrix = GetChannelMatrix();
304 Ptr<UniformPlanarArray> gnbUpa =
305 DynamicCast<UniformPlanarArray>(m_gnbSpectrumPhy->GetAntenna());
306 Ptr<UniformPlanarArray> ueUpa = DynamicCast<UniformPlanarArray>(m_ueSpectrumPhy->GetAntenna());
307 NS_ASSERT_MSG(gnbUpa,
"gNB antenna should be UniformPlanarArray");
308 NS_ASSERT_MSG(ueUpa,
"UE antenna should be UniformPlanarArray");
310 uint16_t txNumCols = gnbUpa->GetNumColumns();
311 uint16_t txNumRows = gnbUpa->GetNumRows();
312 uint16_t rxNumCols = ueUpa->GetNumColumns();
313 uint16_t rxNumRows = ueUpa->GetNumRows();
315 NS_ASSERT(gnbUpa->GetNumElems() && ueUpa->GetNumElems());
317 double txZenithStep = 180 / ((txNumRows > 1 ? m_oversamplingFactor : 1) * txNumRows);
318 double txSectorStep = 1.0 / (txNumCols > 1 ? m_oversamplingFactor : 1);
319 double rxZenithStep = 180 / ((rxNumRows > 1 ? m_oversamplingFactor : 1) * rxNumRows);
320 double rxSectorStep = 1.0 / (rxNumCols > 1 ? m_oversamplingFactor : 1);
322 for (
double txZenith = 0; txZenith < 180; txZenith += txZenithStep)
325 double txTheta = txZenith + txZenithStep * 0.5;
326 for (
double txSector = 0; txSector < txNumCols; txSector += txSectorStep)
328 NS_ASSERT(txSector < UINT16_MAX);
329 m_gnbSpectrumPhy->GetBeamManager()->SetSector(txSector, txTheta);
330 PhasedArrayModel::ComplexVector gnbW =
331 m_gnbSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
333 for (
double rxZenith = 0; rxZenith < 180; rxZenith += txZenithStep)
337 double rxTheta = rxZenith + rxZenithStep * 0.5;
338 for (
double rxSector = 0; rxSector < rxNumCols; rxSector += rxSectorStep)
340 NS_ASSERT(rxSector < UINT16_MAX);
341 m_ueSpectrumPhy->GetBeamManager()->SetSector(rxSector, rxTheta);
342 PhasedArrayModel::ComplexVector ueW =
343 m_ueSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
345 NS_ABORT_MSG_IF(gnbW.GetSize() == 0 || ueW.GetSize() == 0,
346 "Beamforming vectors must be initialized in order to calculate "
347 "the long term matrix.");
349 const UniformPlanarArray::ComplexVector estimatedLongTermComponent =
350 GetEstimatedLongTermComponent(
354 m_gnbSpectrumPhy->GetObject<MobilityModel>(),
355 m_ueSpectrumPhy->GetObject<MobilityModel>(),
357 m_gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>(),
358 m_ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>());
360 double estimatedLongTermMetric =
361 CalculateTheEstimatedLongTermMetric(estimatedLongTermComponent);
364 " Estimated long term metric value: "
365 << estimatedLongTermMetric <<
" gnb theta " << txTheta <<
" ue theta "
366 << rxTheta <<
" gnb sector "
367 << (M_PI *
static_cast<double>(txSector) /
static_cast<double>(txNumCols) -
371 << (M_PI *
static_cast<double>(rxSector) /
static_cast<double>(rxNumCols) -
375 if (max < estimatedLongTermMetric)
377 max = estimatedLongTermMetric;
378 maxTxSector = txSector;
379 maxRxSector = rxSector;
380 maxTxTheta = txTheta;
381 maxRxTheta = rxTheta;
390 BeamformingVectorPair bfPair = std::make_pair(
393 BeamId(maxTxSector * (txNumCols > 1 ? m_oversamplingFactor : 1), maxTxTheta))),
396 BeamId(maxRxSector * (rxNumCols > 1 ? m_oversamplingFactor : 1), maxRxTheta))));
398 "Beamforming vectors for gNB with node id: "
399 << m_gnbSpectrumPhy->GetMobility()->GetObject<Node>()->GetId()
400 <<
" and UE with node id: " << m_ueSpectrumPhy->GetMobility()->GetObject<Node>()->GetId()
401 <<
" txTheta " << maxTxTheta <<
" rxTheta " << maxRxTheta <<
" tx sector "
402 << (M_PI *
static_cast<double>(maxTxSector) /
static_cast<double>(txNumCols) - 0.5 * M_PI) /
405 << (M_PI *
static_cast<double>(maxRxSector) /
static_cast<double>(rxNumCols) - 0.5 * M_PI) /
412RealisticBeamformingAlgorithm::CalculateTheEstimatedLongTermMetric(
413 const UniformPlanarArray::ComplexVector& longTermComponent)
const
415 NS_LOG_FUNCTION(
this);
418 for (std::complex<double> c : longTermComponent.GetValues())
420 totalSum += c.imag() * c.imag() + c.real() * c.real();
425UniformPlanarArray::ComplexVector
426RealisticBeamformingAlgorithm::GetEstimatedLongTermComponent(
427 const Ptr<const MatrixBasedChannelModel::ChannelMatrix>& channelMatrix,
428 const UniformPlanarArray::ComplexVector& aW,
429 const UniformPlanarArray::ComplexVector& bW,
430 Ptr<const MobilityModel> a,
431 Ptr<const MobilityModel> b,
433 Ptr<const PhasedArrayModel> aArray,
434 Ptr<const PhasedArrayModel> bArray)
const
436 NS_LOG_FUNCTION(
this);
440 UniformPlanarArray::ComplexVector sW;
441 UniformPlanarArray::ComplexVector uW;
442 if (!channelMatrix->IsReverse(aArray->GetId(), bArray->GetId()))
453 uint16_t sAntenna =
static_cast<uint16_t
>(sW.GetSize());
454 uint16_t uAntenna =
static_cast<uint16_t
>(uW.GetSize());
456 NS_LOG_DEBUG(
"Calculate the estimation of the long term component with sAntenna: "
457 << sAntenna <<
" uAntenna: " << uAntenna);
458 NS_ABORT_IF(srsSinr == 0);
460 double varError = 1 / (srsSinr);
461 uint8_t numCluster =
static_cast<uint8_t
>(channelMatrix->m_channel.GetNumPages());
463 UniformPlanarArray::ComplexVector estimatedlongTerm(numCluster);
464 for (uint8_t cIndex = 0; cIndex < numCluster; cIndex++)
466 std::complex<double> txSum(0, 0);
467 for (uint16_t sIndex = 0; sIndex < sAntenna; sIndex++)
469 std::complex<double> rxSum(0, 0);
470 for (uint16_t uIndex = 0; uIndex < uAntenna; uIndex++)
474 std::complex<double> error =
475 std::complex<double>(m_normalRandomVariable->GetValue(0, sqrt(0.5) * varError),
476 m_normalRandomVariable->GetValue(0, sqrt(0.5) * varError));
477 std::complex<double> hEstimate =
478 channelMatrix->m_channel(uIndex, sIndex, cIndex) + error;
479 rxSum += uW[uIndex] * (hEstimate);
481 txSum = txSum + sW[sIndex] * rxSum;
483 estimatedlongTerm[cIndex] = txSum;
485 return estimatedlongTerm;
Representation of a beam id.
std::pair< PhasedArrayModel::ComplexVector, BeamId > BeamformingVector
Physical representation of a beam.