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 }
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
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
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
Class holding the azimuth and inclination angles of spherical coordinates.
Definition: angles.h:118
#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
ComplexVector GetBeamformingVector(void) const
Returns the beamforming vector that is currently being used.
#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)
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
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
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
std::vector< std::complex< double > > ComplexVector
type definition for complex vectors
#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 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
static void DoBeamforming(Ptr< NetDevice > thisDevice, Ptr< PhasedArrayModel > thisAntenna, Ptr< NetDevice > otherDevice)
Perform the beamforming using the DFT beamforming method.
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.