5G-LENA  nr-v3.0-29-g83cc959
The 5G/NR module for the ns-3 simulator
beam-manager.cc
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 
3 // Copyright (c) 2020 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4 //
5 // SPDX-License-Identifier: GPL-2.0-only
6 
7 #include "beam-manager.h"
8 
9 #include <ns3/boolean.h>
10 #include <ns3/log.h>
11 #include <ns3/node.h>
12 #include <ns3/simulator.h>
13 #include <ns3/uinteger.h>
14 
15 namespace ns3
16 {
17 
18 NS_LOG_COMPONENT_DEFINE("BeamManager");
19 NS_OBJECT_ENSURE_REGISTERED(BeamManager);
20 
22 {
23  // TODO Auto-generated constructor stub
24 }
25 
26 void
27 BeamManager::Configure(const Ptr<UniformPlanarArray>& antennaArray)
28 {
29  m_antennaArray = antennaArray;
31 }
32 
33 PhasedArrayModel::ComplexVector
35 {
36  return v.first;
37 }
38 
39 BeamId
41 {
42  return v.second;
43 }
44 
45 Ptr<const UniformPlanarArray>
47 {
48  return m_antennaArray;
49 }
50 
52 {
53  // TODO Auto-generated destructor stub
54 }
55 
56 TypeId
58 {
59  static TypeId tid =
60  TypeId("ns3::BeamManager").SetParent<Object>().AddConstructor<BeamManager>();
61  return tid;
62 }
63 
64 void
65 BeamManager::SetPredefinedBeam(PhasedArrayModel::ComplexVector predefinedBeam)
66 {
67  NS_LOG_FUNCTION(this);
68  NS_ABORT_MSG_IF(predefinedBeam.GetSize() == 0, "Cannot assign an empty predefined beam");
69  NS_ABORT_MSG_IF(predefinedBeam.GetSize() != m_antennaArray->GetNumElems(),
70  "Cannot assign a predefined beamforming vector whose dimension is not "
71  "compatible with antenna array");
72  m_predefinedDirTxRxW = std::make_pair(predefinedBeam, PREDEFINED_BEAM_ID);
73 }
74 
75 void
76 BeamManager::SetPredefinedBeam(uint16_t sector, double elevation)
77 {
78  NS_LOG_FUNCTION(this);
79  m_predefinedDirTxRxW = std::make_pair(CreateDirectionalBfv(m_antennaArray, sector, elevation),
80  BeamId(sector, elevation));
81 }
82 
83 void
84 BeamManager::SaveBeamformingVector(const BeamformingVector& bfv, const Ptr<const NetDevice>& device)
85 {
86  NS_LOG_INFO("Save beamforming vector toward device with node id:"
87  << device->GetNode()->GetId() << " with BeamId:" << bfv.second);
88 
89  if (m_predefinedDirTxRxW.first.GetSize() != 0)
90  {
91  NS_LOG_WARN("Saving beamforming vector for device, while there is also a predefined "
92  "beamforming vector defined to be used for all transmissions.");
93  }
94 
95  if (device != nullptr)
96  {
97  BeamformingStorage::iterator iter = m_beamformingVectorMap.find(device);
98  if (iter != m_beamformingVectorMap.end())
99  {
100  (*iter).second = bfv;
101  }
102  else
103  {
104  m_beamformingVectorMap.insert(std::make_pair(device, bfv));
105  }
106  }
107 }
108 
109 void
110 BeamManager::ChangeBeamformingVector(const Ptr<const NetDevice>& device)
111 {
112  NS_LOG_FUNCTION(this);
113 
114  BeamformingStorage::iterator it = m_beamformingVectorMap.find(device);
115  if (it == m_beamformingVectorMap.end())
116  {
117  NS_LOG_INFO("Could not find the beamforming vector for the provided device");
118 
119  // if there is no beam defined for this specific device then use a
120  // predefined beam if specified and if not, then use quasi omni
121  if (m_predefinedDirTxRxW.first.GetSize() != 0)
122  {
123  m_antennaArray->SetBeamformingVector(m_predefinedDirTxRxW.first);
124  }
125  else
126  {
128  }
129  }
130  else
131  {
132  NS_LOG_INFO("Beamforming vector found");
133  m_antennaArray->SetBeamformingVector(it->second.first);
134  }
135 }
136 
137 PhasedArrayModel::ComplexVector
139 {
140  return m_antennaArray->GetBeamformingVector();
141 }
142 
143 void
145 {
146  NS_LOG_FUNCTION(this);
147 
148  UintegerValue numRows;
149  UintegerValue numColumns;
150  m_antennaArray->GetAttribute("NumRows", numRows);
151  m_antennaArray->GetAttribute("NumColumns", numColumns);
152 
160  if (numRows.Get() != m_numRows || numColumns.Get() != m_numColumns ||
161  m_isPolDual != m_antennaArray->IsDualPol())
162  {
163  m_isPolDual = m_antennaArray->IsDualPol();
164  m_numPortElems = m_antennaArray->GetNumElemsPerPort();
165  m_numRows = numRows.Get();
166  m_numColumns = numColumns.Get();
167  m_omniTxRxW = std::make_pair(CreateQuasiOmniBfv(m_antennaArray), OMNI_BEAM_ID);
168  }
169 
170  m_antennaArray->SetBeamformingVector(m_omniTxRxW.first);
171 }
172 
173 PhasedArrayModel::ComplexVector
174 BeamManager::GetBeamformingVector(const Ptr<NetDevice>& device) const
175 {
176  NS_LOG_FUNCTION(this);
177  PhasedArrayModel::ComplexVector beamformingVector;
178  BeamformingStorage::const_iterator it = m_beamformingVectorMap.find(device);
179  if (it != m_beamformingVectorMap.end())
180  {
181  beamformingVector = it->second.first;
182  }
183  else
184  {
185  // it there is no specific beam saved for this device, check
186  // whether we have a predefined beam set, if yes return its vector
187  if (m_predefinedDirTxRxW.first.GetSize() != 0)
188  {
189  beamformingVector = m_predefinedDirTxRxW.first;
190  }
191  else
192  {
193  beamformingVector = m_antennaArray->GetBeamformingVector();
194  }
195  }
196  return beamformingVector;
197 }
198 
199 BeamId
200 BeamManager::GetBeamId(const Ptr<NetDevice>& device) const
201 {
202  BeamId beamId;
203  BeamformingStorage::const_iterator it = m_beamformingVectorMap.find(device);
204  if (it != m_beamformingVectorMap.end())
205  {
206  beamId = it->second.second;
207  }
208  else
209  {
210  // it there is no specific beam saved for this device, check
211  // whether we have a predefined beam set, if yes return its ID
212  if (m_predefinedDirTxRxW.first.GetSize() != 0)
213  {
214  beamId = m_predefinedDirTxRxW.second;
215  }
216  else
217  {
218  beamId = OMNI_BEAM_ID;
219  }
220  }
221  return beamId;
222 }
223 
224 void
225 BeamManager::SetSector(uint16_t sector, double elevation) const
226 {
227  NS_LOG_INFO("Set sector to : " << (unsigned)sector << ", and elevation to: " << elevation);
228  m_antennaArray->SetBeamformingVector(CreateDirectionalBfv(m_antennaArray, sector, elevation));
229 }
230 
231 void
232 BeamManager::SetSectorAz(double azimuth, double zenith) const
233 {
234  NS_LOG_INFO("Set azimuth to : " << (unsigned)azimuth << ", and zenith to:" << zenith);
235  m_antennaArray->SetBeamformingVector(CreateDirectionalBfvAz(m_antennaArray, azimuth, zenith));
236 }
237 
238 } /* namespace ns3 */
Representation of a beam id.
Definition: beam-id.h:28
static TypeId GetTypeId()
GetTypeId.
Definition: beam-manager.cc:57
BeamManager()
BeamManager constructor.
Definition: beam-manager.cc:21
void SetSectorAz(double azimuth, double zenith) const
Set the Sector.
PhasedArrayModel::ComplexVector GetVector(const BeamformingVector &v) const
Get weight vector from a BeamformingVector.
Definition: beam-manager.cc:34
virtual PhasedArrayModel::ComplexVector GetBeamformingVector(const Ptr< NetDevice > &device) const
Function that returns the beamforming vector weights that is used to communicated with a specified de...
virtual PhasedArrayModel::ComplexVector GetCurrentBeamformingVector()
Function that returns the beamforming vector that is currently being used by the antenna.
BeamId GetBeamId(const BeamformingVector &v) const
Extract the beam id from the beamforming vector specified.
Definition: beam-manager.cc:40
virtual void ChangeToQuasiOmniBeamformingVector()
Change current beamforming vector to quasi-omni beamforming vector.
void Configure(const Ptr< UniformPlanarArray > &antennaArray)
Configures quasi-omni beamforming vector.
Definition: beam-manager.cc:27
void SetSector(uint16_t sector, double elevation) const
Set the Sector.
Ptr< const UniformPlanarArray > GetAntenna() const
Get a pointer to the current antenna.
Definition: beam-manager.cc:46
~BeamManager() override
~BeamManager
Definition: beam-manager.cc:51
virtual void ChangeBeamformingVector(const Ptr< const NetDevice > &device)
Change the beamforming vector for tx/rx to/from specified device.
virtual void SaveBeamformingVector(const BeamformingVector &bfv, const Ptr< const NetDevice > &device)
Function that saves the beamforming weights of the antenna for transmission or reception to/from a sp...
Definition: beam-manager.cc:84
const BeamId PREDEFINED_BEAM_ID
Reserved ID for the predefined directional beam if it cannot be expressed through sector and elevatio...
Definition: beam-id.cc:12
std::pair< PhasedArrayModel::ComplexVector, BeamId > BeamformingVector
Physical representation of a beam.
PhasedArrayModel::ComplexVector CreateDirectionalBfvAz(const Ptr< const UniformPlanarArray > &antenna, double azimuth, double zenith)
Creates a beamforming vector for a given azimuth and zenith.
const BeamId OMNI_BEAM_ID
Name of the OMNI beam.
Definition: beam-id.cc:11
PhasedArrayModel::ComplexVector CreateQuasiOmniBfv(const Ptr< const UniformPlanarArray > &antenna)
Create a quasi omni beamforming vector.
PhasedArrayModel::ComplexVector CreateDirectionalBfv(const Ptr< const UniformPlanarArray > &antenna, uint16_t sector, double elevation)
Creates a beamforming vector for a given sector and elevation.