A Discrete-Event Network Simulator
API
three-gpp-v2v-channel-example.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020, University of Padova, Dep. of Information Engineering, SIGNET lab
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 
39 #include "ns3/buildings-module.h"
40 #include "ns3/mobility-module.h"
41 #include "ns3/core-module.h"
42 #include "ns3/network-module.h"
43 #include <fstream>
44 #include "ns3/three-gpp-antenna-array-model.h"
45 #include "ns3/three-gpp-spectrum-propagation-loss-model.h"
46 #include "ns3/three-gpp-v2v-propagation-loss-model.h"
47 #include "ns3/three-gpp-channel-model.h"
48 
49 using namespace ns3;
50 
51 NS_LOG_COMPONENT_DEFINE ("ThreeGppV2vChannelExample");
52 
56 
63 static void
65 {
66  ThreeGppAntennaArrayModel::ComplexVector antennaWeights;
67 
68  // retrieve the position of the two devices
69  Vector aPos = thisDevice->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
70  Vector bPos = otherDevice->GetNode ()->GetObject<MobilityModel> ()->GetPosition ();
71 
72  // compute the azimuth and the elevation angles
73  Angles completeAngle (bPos,aPos);
74 
75  double hAngleRadian = fmod (completeAngle.phi, 2.0 * M_PI); // the azimuth angle
76  if (hAngleRadian < 0)
77  {
78  hAngleRadian += 2.0 * M_PI;
79  }
80  double vAngleRadian = completeAngle.theta; // the elevation angle
81 
82  // retrieve the number of antenna elements
83  int totNoArrayElements = thisAntenna->GetNumberOfElements ();
84 
85  // the total power is divided equally among the antenna elements
86  double power = 1 / sqrt (totNoArrayElements);
87 
88  // compute the antenna weights
89  for (int ind = 0; ind < totNoArrayElements; ind++)
90  {
91  Vector loc = thisAntenna->GetElementLocation (ind);
92  double phase = -2 * M_PI * (sin (vAngleRadian) * cos (hAngleRadian) * loc.x
93  + sin (vAngleRadian) * sin (hAngleRadian) * loc.y
94  + cos (vAngleRadian) * loc.z);
95  antennaWeights.push_back (exp (std::complex<double> (0, phase)) * power);
96  }
97 
98  // store the antenna weights
99  thisAntenna->SetBeamformingVector (antennaWeights);
100 }
101 
109 static void
111 {
112  Ptr<SpectrumValue> rxPsd = txPsd->Copy ();
113 
114  // check the channel condition
115  Ptr<ChannelCondition> cond = m_condModel->GetChannelCondition (txMob, rxMob);
116 
117  // apply the pathloss
118  double propagationGainDb = m_propagationLossModel->CalcRxPower (0, txMob, rxMob);
119  NS_LOG_DEBUG ("Pathloss " << -propagationGainDb << " dB");
120  double propagationGainLinear = std::pow (10.0, (propagationGainDb) / 10.0);
121  *(rxPsd) *= propagationGainLinear;
122 
123  // apply the fast fading and the beamforming gain
124  rxPsd = m_spectrumLossModel->CalcRxPowerSpectralDensity (rxPsd, txMob, rxMob);
125  NS_LOG_DEBUG ("Average rx power " << 10 * log10 (Sum (*rxPsd) * 180e3) << " dB");
126 
127  // create the noise psd
128  // taken from lte-spectrum-value-helper
129  const double kT_dBm_Hz = -174.0; // dBm/Hz
130  double kT_W_Hz = std::pow (10.0, (kT_dBm_Hz - 30) / 10.0);
131  double noiseFigureLinear = std::pow (10.0, noiseFigure / 10.0);
132  double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
133  Ptr<SpectrumValue> noisePsd = Create <SpectrumValue> (txPsd->GetSpectrumModel ());
134  (*noisePsd) = noisePowerSpectralDensity;
135 
136  // compute the SNR
137  NS_LOG_DEBUG ("Average SNR " << 10 * log10 (Sum (*rxPsd) / Sum (*noisePsd)) << " dB");
138 
139  // print the SNR and pathloss values in the snr-trace.txt file
140  std::ofstream f;
141  f.open ("example-output.txt", std::ios::out | std::ios::app);
142  f << Simulator::Now ().GetSeconds () << " " // time [s]
143  << txMob->GetPosition ().x << " "
144  << txMob->GetPosition ().y << " "
145  << rxMob->GetPosition ().x << " "
146  << rxMob->GetPosition ().y << " "
147  << cond->GetLosCondition () << " " // channel state
148  << 10 * log10 (Sum (*rxPsd) / Sum (*noisePsd)) << " " // SNR [dB]
149  << -propagationGainDb << std::endl; // pathloss [dB]
150  f.close ();
151 }
152 
158 void
160 {
161  std::ofstream outFile;
162  outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
163  if (!outFile.is_open ())
164  {
165  NS_LOG_ERROR ("Can't open file " << filename);
166  return;
167  }
168  uint32_t index = 0;
169  for (BuildingList::Iterator it = BuildingList::Begin (); it != BuildingList::End (); ++it)
170  {
171  ++index;
172  Box box = (*it)->GetBoundaries ();
173  outFile << "set object " << index
174  << " rect from " << box.xMin << "," << box.yMin
175  << " to " << box.xMax << "," << box.yMax
176  << std::endl;
177  }
178 }
179 
180 int
181 main (int argc, char *argv[])
182 {
183  double frequency = 28.0e9; // operating frequency in Hz
184  double txPow_dbm = 30.0; // tx power in dBm
185  double noiseFigure = 9.0; // noise figure in dB
186  Time simTime = Seconds (40); // simulation time
187  Time timeRes = MilliSeconds (10); // time resolution
188  std::string scenario = "V2V-Urban"; // 3GPP propagation scenario, V2V-Urban or V2V-Highway
189  double vScatt = 0; // maximum speed of the vehicles in the scenario [m/s]
190  double subCarrierSpacing = 60e3; // subcarrier spacing in kHz
191  uint32_t numRb = 275; // number of resource blocks
192 
193  CommandLine cmd (__FILE__);
194  cmd.AddValue ("frequency", "operating frequency in Hz", frequency);
195  cmd.AddValue ("txPow", "tx power in dBm", txPow_dbm);
196  cmd.AddValue ("noiseFigure", "noise figure in dB", noiseFigure);
197  cmd.AddValue ("scenario", "3GPP propagation scenario, V2V-Urban or V2V-Highway", scenario);
198  cmd.Parse (argc, argv);
199 
200  // create the nodes
202  nodes.Create (2);
203 
204  // create the tx and rx devices
205  Ptr<SimpleNetDevice> txDev = CreateObject<SimpleNetDevice> ();
206  Ptr<SimpleNetDevice> rxDev = CreateObject<SimpleNetDevice> ();
207 
208  // associate the nodes and the devices
209  nodes.Get (0)->AddDevice (txDev);
210  txDev->SetNode (nodes.Get (0));
211  nodes.Get (1)->AddDevice (rxDev);
212  rxDev->SetNode (nodes.Get (1));
213 
214  // create the antenna objects and set their dimensions
215  Ptr<ThreeGppAntennaArrayModel> txAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (2), "NumRows", UintegerValue (2), "BearingAngle", DoubleValue (-M_PI / 2));
216  Ptr<ThreeGppAntennaArrayModel> rxAntenna = CreateObjectWithAttributes<ThreeGppAntennaArrayModel> ("NumColumns", UintegerValue (2), "NumRows", UintegerValue (2), "BearingAngle", DoubleValue (M_PI / 2));
217 
218  Ptr<MobilityModel> txMob;
219  Ptr<MobilityModel> rxMob;
220  if (scenario == "V2V-Urban")
221  {
222  // 3GPP defines that the maximum speed in urban scenario is 60 km/h
223  vScatt = 60 / 3.6;
224 
225  // create a grid of buildings
226  double buildingSizeX = 250 - 3.5 * 2 - 3; // m
227  double buildingSizeY = 433 - 3.5 * 2 - 3; // m
228  double streetWidth = 20; // m
229  double buildingHeight = 10; // m
230  uint32_t numBuildingsX = 2;
231  uint32_t numBuildingsY = 2;
232  double maxAxisX = (buildingSizeX + streetWidth) * numBuildingsX;
233  double maxAxisY = (buildingSizeY + streetWidth) * numBuildingsY;
234 
235  std::vector<Ptr<Building> > buildingVector;
236  for (uint32_t buildingIdX = 0; buildingIdX < numBuildingsX; ++buildingIdX)
237  {
238  for (uint32_t buildingIdY = 0; buildingIdY < numBuildingsY; ++buildingIdY)
239  {
240  Ptr < Building > building;
241  building = CreateObject<Building> ();
242 
243  building->SetBoundaries (Box (buildingIdX * (buildingSizeX + streetWidth),
244  buildingIdX * (buildingSizeX + streetWidth) + buildingSizeX,
245  buildingIdY * (buildingSizeY + streetWidth),
246  buildingIdY * (buildingSizeY + streetWidth) + buildingSizeY,
247  0.0, buildingHeight));
248  building->SetNRoomsX (1);
249  building->SetNRoomsY (1);
250  building->SetNFloors (1);
251  buildingVector.push_back (building);
252  }
253  }
254 
255  // set the mobility model
256  double vTx = vScatt;
257  double vRx = vScatt / 2;
258  txMob = CreateObject<WaypointMobilityModel> ();
259  rxMob = CreateObject<WaypointMobilityModel> ();
260  Time nextWaypoint = Seconds (0.0);
261  txMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, 1.0, 1.5)));
262  nextWaypoint += Seconds ((maxAxisY - streetWidth) / 2 / vTx);
263  txMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, maxAxisY / 2 - streetWidth / 2, 1.5)));
264  nextWaypoint += Seconds ((maxAxisX - streetWidth) / 2 / vTx);
265  txMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (0.0, maxAxisY / 2 - streetWidth / 2, 1.5)));
266  nextWaypoint = Seconds (0.0);
267  rxMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, 0.0, 1.5)));
268  nextWaypoint += Seconds (maxAxisY / vRx);
269  rxMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, maxAxisY, 1.5)));
270 
271  nodes.Get (0)->AggregateObject (txMob);
272  nodes.Get (1)->AggregateObject (rxMob);
273 
274  // create the channel condition model
275  m_condModel = CreateObject<ThreeGppV2vUrbanChannelConditionModel> ();
276 
277  // create the propagation loss model
278  m_propagationLossModel = CreateObject<ThreeGppV2vUrbanPropagationLossModel> ();
279  }
280  else if (scenario == "V2V-Highway")
281  {
282  // Two vehicles are travelling one behid the other with constant velocity
283  // along the y axis. The distance between the two vehicles is 20 meters.
284 
285  // 3GPP defines that the maximum speed in urban scenario is 140 km/h
286  vScatt = 140 / 3.6;
287  double vTx = vScatt;
288  double vRx = vScatt / 2;
289 
290  txMob = CreateObject<ConstantVelocityMobilityModel> ();
291  rxMob = CreateObject<ConstantVelocityMobilityModel> ();
292  txMob->GetObject<ConstantVelocityMobilityModel> ()->SetPosition (Vector (300.0, 20.0, 1.5));
293  txMob->GetObject<ConstantVelocityMobilityModel> ()->SetVelocity (Vector (0.0, vTx, 0.0));
294  rxMob->GetObject<ConstantVelocityMobilityModel> ()->SetPosition (Vector (300.0, 0.0, 1.5));
295  rxMob->GetObject<ConstantVelocityMobilityModel> ()->SetVelocity (Vector (0.0, vRx, 0.0));
296 
297  nodes.Get (0)->AggregateObject (txMob);
298  nodes.Get (1)->AggregateObject (rxMob);
299 
300  // create the channel condition model
301  m_condModel = CreateObject<ThreeGppV2vHighwayChannelConditionModel> ();
302 
303  // create the propagation loss model
304  m_propagationLossModel = CreateObject<ThreeGppV2vHighwayPropagationLossModel> ();
305  }
306  else
307  {
308  NS_FATAL_ERROR ("Unknown scenario");
309  }
310 
311  m_condModel->SetAttribute ("UpdatePeriod", TimeValue (MilliSeconds (100)));
312 
313  m_propagationLossModel->SetAttribute ("Frequency", DoubleValue (frequency));
314  m_propagationLossModel->SetAttribute ("ShadowingEnabled", BooleanValue (false));
315  m_propagationLossModel->SetAttribute ("ChannelConditionModel", PointerValue (m_condModel));
316 
317  // create the channel model
318  Ptr<ThreeGppChannelModel> channelModel = CreateObject<ThreeGppChannelModel> ();
319  channelModel->SetAttribute ("Scenario", StringValue (scenario));
320  channelModel->SetAttribute ("Frequency", DoubleValue (frequency));
321  channelModel->SetAttribute ("ChannelConditionModel", PointerValue (m_condModel));
322 
323  // create the spectrum propagation loss model
324  m_spectrumLossModel = CreateObjectWithAttributes<ThreeGppSpectrumPropagationLossModel> ("ChannelModel", PointerValue (channelModel));
325  m_spectrumLossModel->SetAttribute ("vScatt", DoubleValue (vScatt));
326 
327  // initialize the devices in the ThreeGppSpectrumPropagationLossModel
328  m_spectrumLossModel->AddDevice (txDev, txAntenna);
329  m_spectrumLossModel->AddDevice (rxDev, rxAntenna);
330 
332 
333  // set the beamforming vectors
334  DoBeamforming (txDev, txAntenna, rxDev);
335  DoBeamforming (rxDev, rxAntenna, txDev);
336 
337  // create the tx power spectral density
338  Bands rbs;
339  double freqSubBand = frequency;
340  for (uint16_t n = 0; n < numRb; ++n)
341  {
342  BandInfo rb;
343  rb.fl = freqSubBand;
344  freqSubBand += subCarrierSpacing / 2;
345  rb.fc = freqSubBand;
346  freqSubBand += subCarrierSpacing / 2;
347  rb.fh = freqSubBand;
348  rbs.push_back (rb);
349  }
350  Ptr<SpectrumModel> spectrumModel = Create<SpectrumModel> (rbs);
351  Ptr<SpectrumValue> txPsd = Create <SpectrumValue> (spectrumModel);
352  double txPow_w = std::pow (10., (txPow_dbm - 30) / 10);
353  double txPowDens = (txPow_w / (numRb * subCarrierSpacing));
354  (*txPsd) = txPowDens;
355 
356  for (int i = 0; i < simTime / timeRes; i++)
357  {
358  Simulator::Schedule (timeRes * i, &ComputeSnr, txMob, rxMob, txPsd, noiseFigure);
359  }
360 
361  // initialize the output file
362  std::ofstream f;
363  f.open ("example-output.txt", std::ios::out);
364  f << "Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState SNR[dB] Pathloss[dB]" << std::endl;
365  f.close ();
366 
367  // print the list of buildings to file
368  PrintGnuplottableBuildingListToFile ("buildings.txt");
369 
370  Simulator::Run ();
372  return 0;
373 }
double f(double x, void *params)
Definition: 80211b.c:70
Class holding the azimuth and inclination angles of spherical coordinates.
Definition: angles.h:119
AttributeValue implementation for Boolean.
Definition: boolean.h:37
a 3d box
Definition: box.h:35
double yMax
The y coordinate of the top bound of the box.
Definition: box.h:116
double xMin
The x coordinate of the left bound of the box.
Definition: box.h:110
double yMin
The y coordinate of the bottom bound of the box.
Definition: box.h:114
double xMax
The x coordinate of the right bound of the box.
Definition: box.h:112
std::vector< Ptr< Building > >::const_iterator Iterator
Const Iterator.
Definition: building-list.h:40
static Iterator End(void)
static Iterator Begin(void)
static void Install(Ptr< Node > node)
Install the MobilityBuildingInfo to a node.
Parse command-line arguments.
Definition: command-line.h:229
Mobility model for which the current speed does not change once it has been set and until it is set a...
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
Keep track of the current position and velocity of an object.
Vector GetPosition(void) const
virtual Ptr< Node > GetNode(void) const =0
keep track of a set of node pointers.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:256
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
Ptr< SpectrumValue > CalcRxPowerSpectralDensity(Ptr< const SpectrumValue > txPsd, Ptr< const MobilityModel > a, Ptr< const MobilityModel > b, Ptr< const PhasedArrayModel > aPhasedArrayModel, Ptr< const PhasedArrayModel > bPhasedArrayModel) const
This method is to be called to calculate.
Hold objects of type Ptr<T>.
Definition: pointer.h:37
double CalcRxPower(double txPowerDbm, Ptr< MobilityModel > a, Ptr< MobilityModel > b) const
Returns the Rx Power taking into account all the PropagationLossModel(s) chained to the current one.
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Hold variables of type string.
Definition: string.h:41
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
AttributeValue implementation for Time.
Definition: nstime.h:1308
Hold an unsigned integer type.
Definition: uinteger.h:44
a (time, location) pair.
Definition: waypoint.h:36
Waypoint-based mobility model.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
nodes
Definition: first.py:32
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::vector< BandInfo > Bands
Container of BandInfo.
double Sum(const SpectrumValue &x)
cmd
Definition: second.py:35
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
static Ptr< ChannelConditionModel > m_condModel
the ChannelConditionModel object
static Ptr< ThreeGppPropagationLossModel > m_propagationLossModel
the PropagationLossModel object
static void DoBeamforming(Ptr< NetDevice > thisDevice, Ptr< ThreeGppAntennaArrayModel > thisAntenna, Ptr< NetDevice > otherDevice)
Perform the beamforming using the DFT beamforming method.
void PrintGnuplottableBuildingListToFile(std::string filename)
Generates a GNU-plottable file representig the buildings deployed in the scenario.
static Ptr< ThreeGppSpectrumPropagationLossModel > m_spectrumLossModel
the SpectrumPropagationLossModel object
static void ComputeSnr(Ptr< MobilityModel > txMob, Ptr< MobilityModel > rxMob, Ptr< const SpectrumValue > txPsd, double noiseFigure)
Compute the average SNR.
static void SetPosition(Ptr< Node > node, Vector position)
Definition: wifi-ap.cc:89
static Vector GetPosition(Ptr< Node > node)
Definition: wifi-ap.cc:96