A Discrete-Event Network Simulator
API
three-gpp-two-ray-channel-calibration.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022 SIGNET Lab, Department of Information Engineering,
3  * University of Padova
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  */
19 
20 #include <ns3/command-line.h>
21 #include <ns3/core-module.h>
22 #include <ns3/double.h>
23 #include <ns3/isotropic-antenna-model.h>
24 #include <ns3/mobility-helper.h>
25 #include <ns3/node-container.h>
26 #include <ns3/object-factory.h>
27 #include <ns3/pointer.h>
28 #include <ns3/string.h>
29 #include <ns3/three-gpp-channel-model.h>
30 #include <ns3/three-gpp-propagation-loss-model.h>
31 #include <ns3/three-gpp-spectrum-propagation-loss-model.h>
32 #include <ns3/two-ray-spectrum-propagation-loss-model.h>
33 #include <ns3/uinteger.h>
34 #include <ns3/uniform-planar-array.h>
35 
36 NS_LOG_COMPONENT_DEFINE("ThreeGppTwoRayChannelCalibration");
37 
38 using namespace ns3;
39 
40 // Calibration results actually show a weak dependence with respect to the carrier frequency
41 constexpr double FC_STEP = 5e9;
42 
43 // 500 MHz, as to provide a fit for the whole frequency range supported by the TR 38.901 model
44 constexpr double MIN_FC = 500e6;
45 
46 // 100 GHz, as to provide a fit for the whole frequency range supported by the TR 38.901 model
47 constexpr double MAX_FC = 100e9;
48 
49 // Results are independent from this
50 constexpr double BW = 200e6;
51 
52 // Results are independent from this, it dictate sonly the resolution of the PSD.
53 // This value corresponds to numerology index 2 of the 5G NR specifications
54 constexpr double RB_WIDTH = 60e3;
55 
56 const std::vector<std::string> LOS_CONDITIONS{
57  "LOS",
58  "NLOS",
59 };
60 
61 const std::vector<std::string> THREE_GPP_SCENARIOS{
62  "RMa",
63  "UMa",
64  "UMi-StreetCanyon",
65  "InH-OfficeOpen",
66  "InH-OfficeMixed",
67 };
68 
70  Create<OutputStreamWrapper>("two-ray-to-three-gpp-calibration.csv", std::ios::out);
71 
72 void
73 LogEndToEndGain(std::string cond, std::string scen, double fc, long int seed, double gain)
74 {
75  *g_outStream->GetStream() << cond << "\t" << scen << "\t" << fc << "\t" << seed << "\t" << gain
76  << "\n";
77 }
78 
79 double
81 {
82  return Integral(*psd);
83 }
84 
87 {
88  uint32_t numRbs = std::floor(BW / RB_WIDTH);
89  double f = fc - (numRbs * RB_WIDTH / 2.0);
90  double powerTx = 0.0;
91 
92  Bands rbs; // A vector representing each resource block
93  std::vector<int> rbsId; // A vector representing the resource block IDs
94  rbsId.reserve(numRbs);
95 
96  for (uint32_t numrb = 0; numrb < numRbs; ++numrb)
97  {
98  BandInfo rb;
99  rb.fl = f;
100  f += RB_WIDTH / 2;
101  rb.fc = f;
102  f += RB_WIDTH / 2;
103  rb.fh = f;
104 
105  rbs.push_back(rb);
106  rbsId.push_back(numrb);
107  }
108  Ptr<SpectrumModel> model = Create<SpectrumModel>(rbs);
109  Ptr<SpectrumValue> txPsd = Create<SpectrumValue>(model);
110 
111  double powerTxW = std::pow(10., (powerTx - 30) / 10);
112  double txPowerDensity = powerTxW / BW;
113 
114  for (auto rbId : rbsId)
115  {
116  (*txPsd)[rbId] = txPowerDensity;
117  }
118 
119  return txPsd;
120 }
121 
122 double
123 ComputeEndToEndGain(std::string cond,
124  std::string scen,
125  double fc,
126  Ptr<Node> a,
127  Ptr<Node> b,
128  Ptr<PhasedArrayModel> aArray,
129  Ptr<PhasedArrayModel> bArray)
130 {
131  // Fix the LOS condition
132  Ptr<ChannelConditionModel> channelConditionModel;
133  if (cond == "LOS")
134  {
135  channelConditionModel = CreateObject<AlwaysLosChannelConditionModel>();
136  }
137  else if (cond == "NLOS")
138  {
139  channelConditionModel = CreateObject<NeverLosChannelConditionModel>();
140  }
141  else
142  {
143  NS_ABORT_MSG("Unsupported channel condition");
144  }
145 
146  // Create the needed objects. These must be created anew each loop, otherwise the channel is
147  // stored and never re-computed.
148  Ptr<ThreeGppSpectrumPropagationLossModel> threeGppSpectrumLossModel =
149  CreateObject<ThreeGppSpectrumPropagationLossModel>();
150  Ptr<ThreeGppChannelModel> threeGppChannelModel = CreateObject<ThreeGppChannelModel>();
151 
152  // Pass the needed pointers between the various spectrum instances
153  threeGppSpectrumLossModel->SetAttribute("ChannelModel", PointerValue(threeGppChannelModel));
154  threeGppChannelModel->SetAttribute("ChannelConditionModel",
155  PointerValue(channelConditionModel));
156 
157  // Create the TX PSD
159  double txPower = ComputePowerSpectralDensityOverallPower(txPsd);
160 
161  // Create TX signal parameters
162  Ptr<SpectrumSignalParameters> signalParams = Create<SpectrumSignalParameters>();
163  signalParams->psd = txPsd;
164 
165  // Set the carrier frequency
166  threeGppChannelModel->SetAttribute("Frequency", DoubleValue(fc));
167 
168  // Set the scenario
169  threeGppChannelModel->SetAttribute("Scenario", StringValue(scen));
170 
171  // Disable all possible sources of variance apart from the multipath fading
172  threeGppChannelModel->SetAttribute("Blockage", BooleanValue(false));
173 
174  // Retrieve the mobility models and the position of the TX and RX nodes
177  Vector aPos = aMob->GetPosition();
178  Vector bPos = bMob->GetPosition();
179 
180  // Compute the relative azimuth and the elevation angles
181  Angles angleBtoA(bPos, aPos);
182  Angles angleAtoB(aPos, bPos);
183 
184  // Create the BF vectors
185  aArray->SetBeamformingVector(aArray->GetBeamformingVector(angleBtoA));
186  bArray->SetBeamformingVector(bArray->GetBeamformingVector(angleAtoB));
187 
188  // Compute the received power due to multipath fading
189  auto rxPsd = threeGppSpectrumLossModel->DoCalcRxPowerSpectralDensity(signalParams,
190  aMob,
191  bMob,
192  aArray,
193  bArray);
194  double rxPower = ComputePowerSpectralDensityOverallPower(rxPsd);
195 
196  return rxPower / txPower;
197 }
198 
199 int
200 main(int argc, char* argv[])
201 {
202  uint32_t numRealizations = 5000; // The number of different channel realizations
203  bool enableOutput = false; // Whether to log the results of the example
204 
205  CommandLine cmd(__FILE__);
206  cmd.AddValue("enableOutput", "Logs the results of the example", enableOutput);
207  cmd.AddValue("numRealizations", "The number of different realizations", numRealizations);
208  cmd.Parse(argc, argv);
209 
210  // Log trace structure
211  if (enableOutput)
212  {
213  *g_outStream->GetStream() << "cond\tscen\tfc\tseed\tgain\n";
214  }
215 
216  // Aggregate them to the corresponding nodes
218  nodes.Create(2);
219 
220  // Create the mobility models for the TX and RX nodes
222  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
223  Vector aPos(0.0, 0.0, 0.0);
224  Vector bPos(10.0, 0.0, 0.0);
225  positionAlloc->Add(aPos);
226  positionAlloc->Add(bPos);
227  mobility.SetPositionAllocator(positionAlloc);
228  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
229  mobility.Install(nodes);
230 
231  // Create the TX and RX phased arrays
232  Ptr<PhasedArrayModel> aPhasedArray =
233  CreateObjectWithAttributes<UniformPlanarArray>("NumColumns",
234  UintegerValue(1),
235  "NumRows",
236  UintegerValue(1));
237  aPhasedArray->SetAntennaElement(PointerValue(CreateObject<IsotropicAntennaModel>()));
238  Ptr<PhasedArrayModel> bPhasedArray =
239  CreateObjectWithAttributes<UniformPlanarArray>("NumColumns",
240  UintegerValue(1),
241  "NumRows",
242  UintegerValue(1));
243  bPhasedArray->SetAntennaElement(PointerValue(CreateObject<IsotropicAntennaModel>()));
244 
245  // Loop over predetermined set of scenarios, LOS conditions and frequencies
246  for (const auto& cond : LOS_CONDITIONS)
247  {
248  for (const auto& scen : THREE_GPP_SCENARIOS)
249  {
250  for (double fc = MIN_FC; fc < MAX_FC; fc += FC_STEP)
251  {
252  for (uint32_t runIdx = 0; runIdx < numRealizations; runIdx++)
253  {
254  double gain = ComputeEndToEndGain(cond,
255  scen,
256  fc,
257  nodes.Get(0),
258  nodes.Get(1),
259  aPhasedArray,
260  bPhasedArray);
261  if (enableOutput)
262  {
263  LogEndToEndGain(cond, scen, fc, runIdx, gain);
264  }
265  }
266  }
267  }
268  }
269 }
double f(double x, void *params)
Definition: 80211b.c:71
Class holding the azimuth and inclination angles of spherical coordinates.
Definition: angles.h:118
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Parse command-line arguments.
Definition: command-line.h:232
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
Vector GetPosition() const
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:200
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
std::ostream * GetStream()
Return a pointer to an ostream previously set in the wrapper.
void SetAntennaElement(Ptr< AntennaModel > antennaElement)
Sets the antenna model to be used.
ComplexVector GetBeamformingVector() const
Returns the beamforming vector that is currently being used.
void SetBeamformingVector(const ComplexVector &beamformingVector)
Sets the beamforming vector to be used.
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Hold variables of type string.
Definition: string.h:56
Ptr< SpectrumValue > DoCalcRxPowerSpectralDensity(Ptr< const SpectrumSignalParameters > params, Ptr< const MobilityModel > a, Ptr< const MobilityModel > b, Ptr< const PhasedArrayModel > aPhasedArrayModel, Ptr< const PhasedArrayModel > bPhasedArrayModel) const override
Computes the received PSD.
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
NodeContainer nodes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double Integral(const SpectrumValue &arg)
std::vector< BandInfo > Bands
Container of BandInfo.
cmd
Definition: second.py:33
mobility
Definition: third.py:96
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
Ptr< SpectrumValue > psd
The Power Spectral Density of the waveform, in linear units.
void LogEndToEndGain(std::string cond, std::string scen, double fc, long int seed, double gain)
const Ptr< OutputStreamWrapper > g_outStream
const std::vector< std::string > LOS_CONDITIONS
Ptr< SpectrumValue > CreateTxPowerSpectralDensity(double fc)
const std::vector< std::string > THREE_GPP_SCENARIOS
constexpr double MIN_FC
double ComputePowerSpectralDensityOverallPower(Ptr< const SpectrumValue > psd)
double ComputeEndToEndGain(std::string cond, std::string scen, double fc, Ptr< Node > a, Ptr< Node > b, Ptr< PhasedArrayModel > aArray, Ptr< PhasedArrayModel > bArray)
constexpr double BW
constexpr double RB_WIDTH
constexpr double MAX_FC
constexpr double FC_STEP