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/uniform-planar-array.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
64 DoBeamforming (Ptr<NetDevice> thisDevice, Ptr<PhasedArrayModel> thisAntenna, Ptr<NetDevice> otherDevice)
65 {
66  PhasedArrayModel::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  PhasedArrayModel::ComplexVector bf = thisAntenna->GetBeamformingVector (completeAngle);
76  thisAntenna->SetBeamformingVector (bf);
77 }
78 
86 static void
88 {
89  Ptr<SpectrumValue> rxPsd = txPsd->Copy ();
90 
91  // check the channel condition
92  Ptr<ChannelCondition> cond = m_condModel->GetChannelCondition (txMob, rxMob);
93 
94  // apply the pathloss
95  double propagationGainDb = m_propagationLossModel->CalcRxPower (0, txMob, rxMob);
96  NS_LOG_DEBUG ("Pathloss " << -propagationGainDb << " dB");
97  double propagationGainLinear = std::pow (10.0, (propagationGainDb) / 10.0);
98  *(rxPsd) *= propagationGainLinear;
99 
100  // apply the fast fading and the beamforming gain
101  rxPsd = m_spectrumLossModel->CalcRxPowerSpectralDensity (rxPsd, txMob, rxMob);
102  NS_LOG_DEBUG ("Average rx power " << 10 * log10 (Sum (*rxPsd) * 180e3) << " dB");
103 
104  // create the noise psd
105  // taken from lte-spectrum-value-helper
106  const double kT_dBm_Hz = -174.0; // dBm/Hz
107  double kT_W_Hz = std::pow (10.0, (kT_dBm_Hz - 30) / 10.0);
108  double noiseFigureLinear = std::pow (10.0, noiseFigure / 10.0);
109  double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
110  Ptr<SpectrumValue> noisePsd = Create <SpectrumValue> (txPsd->GetSpectrumModel ());
111  (*noisePsd) = noisePowerSpectralDensity;
112 
113  // compute the SNR
114  NS_LOG_DEBUG ("Average SNR " << 10 * log10 (Sum (*rxPsd) / Sum (*noisePsd)) << " dB");
115 
116  // print the SNR and pathloss values in the snr-trace.txt file
117  std::ofstream f;
118  f.open ("example-output.txt", std::ios::out | std::ios::app);
119  f << Simulator::Now ().GetSeconds () << " " // time [s]
120  << txMob->GetPosition ().x << " "
121  << txMob->GetPosition ().y << " "
122  << rxMob->GetPosition ().x << " "
123  << rxMob->GetPosition ().y << " "
124  << cond->GetLosCondition () << " " // channel state
125  << 10 * log10 (Sum (*rxPsd) / Sum (*noisePsd)) << " " // SNR [dB]
126  << -propagationGainDb << std::endl; // pathloss [dB]
127  f.close ();
128 }
129 
135 void
137 {
138  std::ofstream outFile;
139  outFile.open (filename.c_str (), std::ios_base::out | std::ios_base::trunc);
140  if (!outFile.is_open ())
141  {
142  NS_LOG_ERROR ("Can't open file " << filename);
143  return;
144  }
145  uint32_t index = 0;
146  for (BuildingList::Iterator it = BuildingList::Begin (); it != BuildingList::End (); ++it)
147  {
148  ++index;
149  Box box = (*it)->GetBoundaries ();
150  outFile << "set object " << index
151  << " rect from " << box.xMin << "," << box.yMin
152  << " to " << box.xMax << "," << box.yMax
153  << std::endl;
154  }
155 }
156 
157 int
158 main (int argc, char *argv[])
159 {
160  double frequency = 28.0e9; // operating frequency in Hz
161  double txPow_dbm = 30.0; // tx power in dBm
162  double noiseFigure = 9.0; // noise figure in dB
163  Time simTime = Seconds (40); // simulation time
164  Time timeRes = MilliSeconds (10); // time resolution
165  std::string scenario = "V2V-Urban"; // 3GPP propagation scenario, V2V-Urban or V2V-Highway
166  double vScatt = 0; // maximum speed of the vehicles in the scenario [m/s]
167  double subCarrierSpacing = 60e3; // subcarrier spacing in kHz
168  uint32_t numRb = 275; // number of resource blocks
169 
170  CommandLine cmd (__FILE__);
171  cmd.AddValue ("frequency", "operating frequency in Hz", frequency);
172  cmd.AddValue ("txPow", "tx power in dBm", txPow_dbm);
173  cmd.AddValue ("noiseFigure", "noise figure in dB", noiseFigure);
174  cmd.AddValue ("scenario", "3GPP propagation scenario, V2V-Urban or V2V-Highway", scenario);
175  cmd.Parse (argc, argv);
176 
177  // create the nodes
179  nodes.Create (2);
180 
181  // create the tx and rx devices
182  Ptr<SimpleNetDevice> txDev = CreateObject<SimpleNetDevice> ();
183  Ptr<SimpleNetDevice> rxDev = CreateObject<SimpleNetDevice> ();
184 
185  // associate the nodes and the devices
186  nodes.Get (0)->AddDevice (txDev);
187  txDev->SetNode (nodes.Get (0));
188  nodes.Get (1)->AddDevice (rxDev);
189  rxDev->SetNode (nodes.Get (1));
190 
191  // create the antenna objects and set their dimensions
192  Ptr<PhasedArrayModel> txAntenna = CreateObjectWithAttributes<UniformPlanarArray> ("NumColumns", UintegerValue (2), "NumRows", UintegerValue (2), "BearingAngle", DoubleValue (-M_PI / 2));
193  Ptr<PhasedArrayModel> rxAntenna = CreateObjectWithAttributes<UniformPlanarArray> ("NumColumns", UintegerValue (2), "NumRows", UintegerValue (2), "BearingAngle", DoubleValue (M_PI / 2));
194 
195  Ptr<MobilityModel> txMob;
196  Ptr<MobilityModel> rxMob;
197  if (scenario == "V2V-Urban")
198  {
199  // 3GPP defines that the maximum speed in urban scenario is 60 km/h
200  vScatt = 60 / 3.6;
201 
202  // create a grid of buildings
203  double buildingSizeX = 250 - 3.5 * 2 - 3; // m
204  double buildingSizeY = 433 - 3.5 * 2 - 3; // m
205  double streetWidth = 20; // m
206  double buildingHeight = 10; // m
207  uint32_t numBuildingsX = 2;
208  uint32_t numBuildingsY = 2;
209  double maxAxisX = (buildingSizeX + streetWidth) * numBuildingsX;
210  double maxAxisY = (buildingSizeY + streetWidth) * numBuildingsY;
211 
212  std::vector<Ptr<Building> > buildingVector;
213  for (uint32_t buildingIdX = 0; buildingIdX < numBuildingsX; ++buildingIdX)
214  {
215  for (uint32_t buildingIdY = 0; buildingIdY < numBuildingsY; ++buildingIdY)
216  {
217  Ptr < Building > building;
218  building = CreateObject<Building> ();
219 
220  building->SetBoundaries (Box (buildingIdX * (buildingSizeX + streetWidth),
221  buildingIdX * (buildingSizeX + streetWidth) + buildingSizeX,
222  buildingIdY * (buildingSizeY + streetWidth),
223  buildingIdY * (buildingSizeY + streetWidth) + buildingSizeY,
224  0.0, buildingHeight));
225  building->SetNRoomsX (1);
226  building->SetNRoomsY (1);
227  building->SetNFloors (1);
228  buildingVector.push_back (building);
229  }
230  }
231 
232  // set the mobility model
233  double vTx = vScatt;
234  double vRx = vScatt / 2;
235  txMob = CreateObject<WaypointMobilityModel> ();
236  rxMob = CreateObject<WaypointMobilityModel> ();
237  Time nextWaypoint = Seconds (0.0);
238  txMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, 1.0, 1.5)));
239  nextWaypoint += Seconds ((maxAxisY - streetWidth) / 2 / vTx);
240  txMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, maxAxisY / 2 - streetWidth / 2, 1.5)));
241  nextWaypoint += Seconds ((maxAxisX - streetWidth) / 2 / vTx);
242  txMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (0.0, maxAxisY / 2 - streetWidth / 2, 1.5)));
243  nextWaypoint = Seconds (0.0);
244  rxMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, 0.0, 1.5)));
245  nextWaypoint += Seconds (maxAxisY / vRx);
246  rxMob->GetObject<WaypointMobilityModel> ()->AddWaypoint (Waypoint (nextWaypoint, Vector (maxAxisX / 2 - streetWidth / 2, maxAxisY, 1.5)));
247 
248  nodes.Get (0)->AggregateObject (txMob);
249  nodes.Get (1)->AggregateObject (rxMob);
250 
251  // create the channel condition model
252  m_condModel = CreateObject<ThreeGppV2vUrbanChannelConditionModel> ();
253 
254  // create the propagation loss model
255  m_propagationLossModel = CreateObject<ThreeGppV2vUrbanPropagationLossModel> ();
256  }
257  else if (scenario == "V2V-Highway")
258  {
259  // Two vehicles are travelling one behid the other with constant velocity
260  // along the y axis. The distance between the two vehicles is 20 meters.
261 
262  // 3GPP defines that the maximum speed in urban scenario is 140 km/h
263  vScatt = 140 / 3.6;
264  double vTx = vScatt;
265  double vRx = vScatt / 2;
266 
267  txMob = CreateObject<ConstantVelocityMobilityModel> ();
268  rxMob = CreateObject<ConstantVelocityMobilityModel> ();
269  txMob->GetObject<ConstantVelocityMobilityModel> ()->SetPosition (Vector (300.0, 20.0, 1.5));
270  txMob->GetObject<ConstantVelocityMobilityModel> ()->SetVelocity (Vector (0.0, vTx, 0.0));
271  rxMob->GetObject<ConstantVelocityMobilityModel> ()->SetPosition (Vector (300.0, 0.0, 1.5));
272  rxMob->GetObject<ConstantVelocityMobilityModel> ()->SetVelocity (Vector (0.0, vRx, 0.0));
273 
274  nodes.Get (0)->AggregateObject (txMob);
275  nodes.Get (1)->AggregateObject (rxMob);
276 
277  // create the channel condition model
278  m_condModel = CreateObject<ThreeGppV2vHighwayChannelConditionModel> ();
279 
280  // create the propagation loss model
281  m_propagationLossModel = CreateObject<ThreeGppV2vHighwayPropagationLossModel> ();
282  }
283  else
284  {
285  NS_FATAL_ERROR ("Unknown scenario");
286  }
287 
288  m_condModel->SetAttribute ("UpdatePeriod", TimeValue (MilliSeconds (100)));
289 
290  m_propagationLossModel->SetAttribute ("Frequency", DoubleValue (frequency));
291  m_propagationLossModel->SetAttribute ("ShadowingEnabled", BooleanValue (false));
292  m_propagationLossModel->SetAttribute ("ChannelConditionModel", PointerValue (m_condModel));
293 
294  // create the channel model
295  Ptr<ThreeGppChannelModel> channelModel = CreateObject<ThreeGppChannelModel> ();
296  channelModel->SetAttribute ("Scenario", StringValue (scenario));
297  channelModel->SetAttribute ("Frequency", DoubleValue (frequency));
298  channelModel->SetAttribute ("ChannelConditionModel", PointerValue (m_condModel));
299 
300  // create the spectrum propagation loss model
301  m_spectrumLossModel = CreateObjectWithAttributes<ThreeGppSpectrumPropagationLossModel> ("ChannelModel", PointerValue (channelModel));
302  m_spectrumLossModel->SetAttribute ("vScatt", DoubleValue (vScatt));
303 
304  // initialize the devices in the ThreeGppSpectrumPropagationLossModel
305  m_spectrumLossModel->AddDevice (txDev, txAntenna);
306  m_spectrumLossModel->AddDevice (rxDev, rxAntenna);
307 
309 
310  // set the beamforming vectors
311  DoBeamforming (txDev, txAntenna, rxDev);
312  DoBeamforming (rxDev, rxAntenna, txDev);
313 
314  // create the tx power spectral density
315  Bands rbs;
316  double freqSubBand = frequency;
317  for (uint16_t n = 0; n < numRb; ++n)
318  {
319  BandInfo rb;
320  rb.fl = freqSubBand;
321  freqSubBand += subCarrierSpacing / 2;
322  rb.fc = freqSubBand;
323  freqSubBand += subCarrierSpacing / 2;
324  rb.fh = freqSubBand;
325  rbs.push_back (rb);
326  }
327  Ptr<SpectrumModel> spectrumModel = Create<SpectrumModel> (rbs);
328  Ptr<SpectrumValue> txPsd = Create <SpectrumValue> (spectrumModel);
329  double txPow_w = std::pow (10., (txPow_dbm - 30) / 10);
330  double txPowDens = (txPow_w / (numRb * subCarrierSpacing));
331  (*txPsd) = txPowDens;
332 
333  for (int i = 0; i < simTime / timeRes; i++)
334  {
335  Simulator::Schedule (timeRes * i, &ComputeSnr, txMob, rxMob, txPsd, noiseFigure);
336  }
337 
338  // initialize the output file
339  std::ofstream f;
340  f.open ("example-output.txt", std::ios::out);
341  f << "Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState SNR[dB] Pathloss[dB]" << std::endl;
342  f.close ();
343 
344  // print the list of buildings to file
345  PrintGnuplottableBuildingListToFile ("buildings.txt");
346 
347  Simulator::Run ();
349  return 0;
350 }
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
Definition: building-list.h:36
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:228
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
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:185
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
std::vector< std::complex< double > > ComplexVector
type definition for complex vectors
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:557
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:104
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
AttributeValue implementation for Time.
Definition: nstime.h:1353
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:1289
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
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< PhasedArrayModel > 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