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 {
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 }
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
virtual uint64_t GetNumberOfElements(void) const
Returns the number of antenna elements.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
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...
AttributeValue implementation for Boolean.
Definition: boolean.h:36
void SetNRoomsY(uint16_t nroomy)
Definition: building.cc:174
std::vector< std::complex< double > > ComplexVector
type definition for complex vectors
Hold variables of type string.
Definition: string.h:41
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
virtual Ptr< Node > GetNode(void) const =0
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
cmd
Definition: second.py:35
static Iterator End(void)
double theta
the inclination angle in radians
Definition: angles.h:117
LosConditionValue GetLosCondition() const
Get the LosConditionValue contaning the information about the LOS/NLOS state of the channel...
double xMax
The x coordinate of the right bound of the box.
Definition: box.h:112
static Iterator Begin(void)
static void ComputeSnr(Ptr< MobilityModel > txMob, Ptr< MobilityModel > rxMob, Ptr< const SpectrumValue > txPsd, double noiseFigure)
Compute the average SNR.
static Vector GetPosition(Ptr< Node > node)
Definition: wifi-ap.cc:96
std::vector< BandInfo > Bands
Container of BandInfo.
static void SetPosition(Ptr< Node > node, Vector position)
Definition: wifi-ap.cc:89
virtual Vector GetElementLocation(uint64_t index) const
Returns the location of the antenna element with the specified index assuming the left bottom corner ...
a 3d box
Definition: box.h:34
double yMax
The y coordinate of the top bound of the box.
Definition: box.h:116
Keep track of the current position and velocity of an object.
virtual void SetNode(Ptr< Node > node)
nodes
Definition: first.py:32
AttributeValue implementation for Time.
Definition: nstime.h:1353
void PrintGnuplottableBuildingListToFile(std::string filename)
Generates a GNU-plottable file representig the buildings deployed in the scenario.
Hold an unsigned integer type.
Definition: uinteger.h:44
void SetNFloors(uint16_t nfloors)
Definition: building.cc:160
double fc
center frequency
std::vector< Ptr< Building > >::const_iterator Iterator
Definition: building-list.h:36
static Ptr< ChannelConditionModel > m_condModel
the ChannelConditionModel object
double yMin
The y coordinate of the bottom bound of the box.
Definition: box.h:114
Parse command-line arguments.
Definition: command-line.h:227
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
Ptr< SpectrumValue > Copy() const
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void SetBeamformingVector(const ComplexVector &beamformingVector)
Sets the beamforming vector to be used.
double f(double x, void *params)
Definition: 80211b.c:70
static void DoBeamforming(Ptr< NetDevice > thisDevice, Ptr< ThreeGppAntennaArrayModel > thisAntenna, Ptr< NetDevice > otherDevice)
Perform the beamforming using the DFT beamforming method.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double fl
lower limit of subband
keep track of a set of node pointers.
Hold objects of type Ptr<T>.
Definition: pointer.h:36
Ptr< const SpectrumModel > GetSpectrumModel() const
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Vector GetPosition(void) const
static Ptr< ThreeGppSpectrumPropagationLossModel > m_spectrumLossModel
the SpectrumPropagationLossModel object
#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:1289
double phi
the azimuth angle in radians
Definition: angles.h:111
double Sum(const SpectrumValue &x)
Waypoint-based mobility model.
void SetNRoomsX(uint16_t nroomx)
Definition: building.cc:167
Mobility model for which the current speed does not change once it has been set and until it is set a...
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
struct holding the azimuth and inclination angles of spherical coordinates.
Definition: angles.h:71
double fh
upper limit of subband
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
The building block of a SpectrumModel.
a (time, location) pair.
Definition: waypoint.h:35
void SetBoundaries(Box box)
Set the boundaries of the building.
Definition: building.cc:139
static Ptr< ThreeGppPropagationLossModel > m_propagationLossModel
the PropagationLossModel object
double xMin
The x coordinate of the left bound of the box.
Definition: box.h:110
static void Install(Ptr< Node > node)
Install the MobilityBuildingInfo to a node.