A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
three-gpp-v2v-channel-example.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020, University of Padova, Dep. of Information Engineering, SIGNET lab
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8/*
9 * This is an example on how to configure the channel model classes to simulate
10 * a vehicular environment.
11 * The channel condition is determined using the model specified in [1], Table 6.2-1.
12 * The pathloss is determined using the model specified in [1], Table 6.2.1-1.
13 * The model for the fast fading is the one described in 3GPP TR 38.901 v15.0.0,
14 * the model parameters are those specified in [1], Table 6.2.3-1.
15 *
16 * This example generates the output file 'example-output.txt'. Each row of the
17 * file is organized as follows:
18 * Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState SNR[dB] Pathloss[dB]
19 * We also provide a bash script which reads the output file and generates two
20 * figures:
21 * (i) map.gif, a GIF representing the simulation scenario and vehicle mobility;
22 * (ii) snr.png, which represents the behavior of the SNR.
23 *
24 * [1] 3GPP TR 37.885, v15.3.0
25 */
26
27#include "ns3/buildings-module.h"
28#include "ns3/core-module.h"
29#include "ns3/mobility-module.h"
30#include "ns3/network-module.h"
31#include "ns3/spectrum-signal-parameters.h"
32#include "ns3/three-gpp-channel-model.h"
33#include "ns3/three-gpp-spectrum-propagation-loss-model.h"
34#include "ns3/three-gpp-v2v-propagation-loss-model.h"
35#include "ns3/uniform-planar-array.h"
36
37#include <fstream>
38
39using namespace ns3;
40
41/// the log component
42NS_LOG_COMPONENT_DEFINE("ThreeGppV2vChannelExample");
43
45 m_propagationLossModel; //!< the PropagationLossModel object
47 m_spectrumLossModel; //!< the SpectrumPropagationLossModel object
48static Ptr<ChannelConditionModel> m_condModel; //!< the ChannelConditionModel object
49
50/**
51 * @brief A structure that holds the parameters for the ComputeSnr
52 * function. In this way the problem with the limited
53 * number of parameters of method Schedule is avoided.
54 */
56{
57 Ptr<MobilityModel> txMob; //!< the tx mobility model
58 Ptr<MobilityModel> rxMob; //!< the rx mobility model
59 Ptr<SpectrumSignalParameters> txParams; //!< the params of the tx signal
60 double noiseFigure; //!< the noise figure in dB
61 Ptr<PhasedArrayModel> txAntenna; //!< the tx antenna array
62 Ptr<PhasedArrayModel> rxAntenna; //!< the rx antenna array
63};
64
65/**
66 * Perform the beamforming using the DFT beamforming method
67 * @param thisDevice the device performing the beamforming
68 * @param thisAntenna the antenna object associated to thisDevice
69 * @param otherDevice the device towards which point the beam
70 */
71static void
73 Ptr<PhasedArrayModel> thisAntenna,
74 Ptr<NetDevice> otherDevice)
75{
77
78 // retrieve the position of the two devices
79 Vector aPos = thisDevice->GetNode()->GetObject<MobilityModel>()->GetPosition();
80 Vector bPos = otherDevice->GetNode()->GetObject<MobilityModel>()->GetPosition();
81
82 // compute the azimuth and the elevation angles
83 Angles completeAngle(bPos, aPos);
84
85 PhasedArrayModel::ComplexVector bf = thisAntenna->GetBeamformingVector(completeAngle);
86 thisAntenna->SetBeamformingVector(bf);
87}
88
89/**
90 * Compute the average SNR
91 * @param params A structure that holds a bunch of parameters needed by ComputSnr function to
92 * calculate the average SNR
93 */
94static void
96{
97 // check the channel condition
98 Ptr<ChannelCondition> cond = m_condModel->GetChannelCondition(params.txMob, params.rxMob);
99
100 // apply the pathloss
101 double propagationGainDb = m_propagationLossModel->CalcRxPower(0, params.txMob, params.rxMob);
102 NS_LOG_DEBUG("Pathloss " << -propagationGainDb << " dB");
103 double propagationGainLinear = std::pow(10.0, (propagationGainDb) / 10.0);
104 *(params.txParams->psd) *= propagationGainLinear;
105
106 // apply the fast fading and the beamforming gain
107 auto rxParams = m_spectrumLossModel->CalcRxPowerSpectralDensity(params.txParams,
108 params.txMob,
109 params.rxMob,
110 params.txAntenna,
111 params.rxAntenna);
112 Ptr<SpectrumValue> rxPsd = rxParams->psd;
113 NS_LOG_DEBUG("Average rx power " << 10 * log10(Sum(*rxPsd) * 180e3) << " dB");
114
115 // create the noise psd
116 // taken from lte-spectrum-value-helper
117 const double kT_dBm_Hz = -174.0; // dBm/Hz
118 double kT_W_Hz = std::pow(10.0, (kT_dBm_Hz - 30) / 10.0);
119 double noiseFigureLinear = std::pow(10.0, params.noiseFigure / 10.0);
120 double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
121 Ptr<SpectrumValue> noisePsd = Create<SpectrumValue>(params.txParams->psd->GetSpectrumModel());
122 (*noisePsd) = noisePowerSpectralDensity;
123
124 // compute the SNR
125 NS_LOG_DEBUG("Average SNR " << 10 * log10(Sum(*rxPsd) / Sum(*noisePsd)) << " dB");
126
127 // print the SNR and pathloss values in the snr-trace.txt file
128 std::ofstream f;
129 f.open("example-output.txt", std::ios::out | std::ios::app);
130 f << Simulator::Now().GetSeconds() << " " // time [s]
131 << params.txMob->GetPosition().x << " " << params.txMob->GetPosition().y << " "
132 << params.rxMob->GetPosition().x << " " << params.rxMob->GetPosition().y << " "
133 << cond->GetLosCondition() << " " // channel state
134 << 10 * log10(Sum(*rxPsd) / Sum(*noisePsd)) << " " // SNR [dB]
135 << -propagationGainDb << std::endl; // pathloss [dB]
136 f.close();
137}
138
139/**
140 * Generates a GNU-plottable file representing the buildings deployed in the
141 * scenario
142 * @param filename the name of the output file
143 */
144void
146{
147 std::ofstream outFile;
148 outFile.open(filename, std::ios_base::out | std::ios_base::trunc);
149 if (!outFile.is_open())
150 {
151 NS_LOG_ERROR("Can't open file " << filename);
152 return;
153 }
154 uint32_t index = 0;
155 for (auto it = BuildingList::Begin(); it != BuildingList::End(); ++it)
156 {
157 ++index;
158 Box box = (*it)->GetBoundaries();
159 outFile << "set object " << index << " rect from " << box.xMin << "," << box.yMin << " to "
160 << box.xMax << "," << box.yMax << std::endl;
161 }
162}
163
164int
165main(int argc, char* argv[])
166{
167 double frequency = 28.0e9; // operating frequency in Hz
168 double txPow_dbm = 30.0; // tx power in dBm
169 double noiseFigure = 9.0; // noise figure in dB
170 Time simTime = Seconds(40); // simulation time
171 Time timeRes = MilliSeconds(10); // time resolution
172 std::string scenario = "V2V-Urban"; // 3GPP propagation scenario, V2V-Urban or V2V-Highway
173 double vScatt = 0; // maximum speed of the vehicles in the scenario [m/s]
174 double subCarrierSpacing = 60e3; // subcarrier spacing in kHz
175 uint32_t numRb = 275; // number of resource blocks
176
177 CommandLine cmd(__FILE__);
178 cmd.AddValue("frequency", "operating frequency in Hz", frequency);
179 cmd.AddValue("txPow", "tx power in dBm", txPow_dbm);
180 cmd.AddValue("noiseFigure", "noise figure in dB", noiseFigure);
181 cmd.AddValue("scenario", "3GPP propagation scenario, V2V-Urban or V2V-Highway", scenario);
182 cmd.Parse(argc, argv);
183
184 // create the nodes
186 nodes.Create(2);
187
188 // create the tx and rx devices
191
192 // associate the nodes and the devices
193 nodes.Get(0)->AddDevice(txDev);
194 txDev->SetNode(nodes.Get(0));
195 nodes.Get(1)->AddDevice(rxDev);
196 rxDev->SetNode(nodes.Get(1));
197
198 // create the antenna objects and set their dimensions
199 Ptr<PhasedArrayModel> txAntenna =
201 UintegerValue(2),
202 "NumRows",
203 UintegerValue(2),
204 "BearingAngle",
205 DoubleValue(-M_PI / 2));
206 Ptr<PhasedArrayModel> rxAntenna =
208 UintegerValue(2),
209 "NumRows",
210 UintegerValue(2),
211 "BearingAngle",
212 DoubleValue(M_PI / 2));
213
214 Ptr<MobilityModel> txMob;
215 Ptr<MobilityModel> rxMob;
216 if (scenario == "V2V-Urban")
217 {
218 // 3GPP defines that the maximum speed in urban scenario is 60 km/h
219 vScatt = 60 / 3.6;
220
221 // create a grid of buildings
222 double buildingSizeX = 250 - 3.5 * 2 - 3; // m
223 double buildingSizeY = 433 - 3.5 * 2 - 3; // m
224 double streetWidth = 20; // m
225 double buildingHeight = 10; // m
226 uint32_t numBuildingsX = 2;
227 uint32_t numBuildingsY = 2;
228 double maxAxisX = (buildingSizeX + streetWidth) * numBuildingsX;
229 double maxAxisY = (buildingSizeY + streetWidth) * numBuildingsY;
230
231 std::vector<Ptr<Building>> buildingVector;
232 for (uint32_t buildingIdX = 0; buildingIdX < numBuildingsX; ++buildingIdX)
233 {
234 for (uint32_t buildingIdY = 0; buildingIdY < numBuildingsY; ++buildingIdY)
235 {
236 Ptr<Building> building;
237 building = CreateObject<Building>();
238
239 building->SetBoundaries(
240 Box(buildingIdX * (buildingSizeX + streetWidth),
241 buildingIdX * (buildingSizeX + streetWidth) + buildingSizeX,
242 buildingIdY * (buildingSizeY + streetWidth),
243 buildingIdY * (buildingSizeY + streetWidth) + buildingSizeY,
244 0.0,
245 buildingHeight));
246 building->SetNRoomsX(1);
247 building->SetNRoomsY(1);
248 building->SetNFloors(1);
249 buildingVector.push_back(building);
250 }
251 }
252
253 // set the mobility model
254 double vTx = vScatt;
255 double vRx = vScatt / 2;
258 Time nextWaypoint;
259 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
260 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, 1.0, 1.5)));
261 nextWaypoint += Seconds((maxAxisY - streetWidth) / 2 / vTx);
262 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
263 Waypoint(nextWaypoint,
264 Vector(maxAxisX / 2 - streetWidth / 2, maxAxisY / 2 - streetWidth / 2, 1.5)));
265 nextWaypoint += Seconds((maxAxisX - streetWidth) / 2 / vTx);
266 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
267 Waypoint(nextWaypoint, Vector(0.0, maxAxisY / 2 - streetWidth / 2, 1.5)));
268 nextWaypoint = Seconds(0);
269 rxMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
270 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, 0.0, 1.5)));
271 nextWaypoint += Seconds(maxAxisY / vRx);
272 rxMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
273 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, maxAxisY, 1.5)));
274
275 nodes.Get(0)->AggregateObject(txMob);
276 nodes.Get(1)->AggregateObject(rxMob);
277
278 // create the channel condition model
280
281 // create the propagation loss model
283 }
284 else if (scenario == "V2V-Highway")
285 {
286 // Two vehicles are travelling one behid the other with constant velocity
287 // along the y axis. The distance between the two vehicles is 20 meters.
288
289 // 3GPP defines that the maximum speed in urban scenario is 140 km/h
290 vScatt = 140 / 3.6;
291 double vTx = vScatt;
292 double vRx = vScatt / 2;
293
296 txMob->GetObject<ConstantVelocityMobilityModel>()->SetPosition(Vector(300.0, 20.0, 1.5));
297 txMob->GetObject<ConstantVelocityMobilityModel>()->SetVelocity(Vector(0.0, vTx, 0.0));
298 rxMob->GetObject<ConstantVelocityMobilityModel>()->SetPosition(Vector(300.0, 0.0, 1.5));
299 rxMob->GetObject<ConstantVelocityMobilityModel>()->SetVelocity(Vector(0.0, vRx, 0.0));
300
301 nodes.Get(0)->AggregateObject(txMob);
302 nodes.Get(1)->AggregateObject(rxMob);
303
304 // create the channel condition model
306
307 // create the propagation loss model
309 }
310 else
311 {
312 NS_FATAL_ERROR("Unknown scenario");
313 }
314
315 m_condModel->SetAttribute("UpdatePeriod", TimeValue(MilliSeconds(100)));
316
317 m_propagationLossModel->SetAttribute("Frequency", DoubleValue(frequency));
318 m_propagationLossModel->SetAttribute("ShadowingEnabled", BooleanValue(false));
319 m_propagationLossModel->SetAttribute("ChannelConditionModel", PointerValue(m_condModel));
320
321 // create the channel model
323 channelModel->SetAttribute("Scenario", StringValue(scenario));
324 channelModel->SetAttribute("Frequency", DoubleValue(frequency));
325 channelModel->SetAttribute("ChannelConditionModel", PointerValue(m_condModel));
326 channelModel->SetAttribute("vScatt", DoubleValue(vScatt));
327
328 // create the spectrum propagation loss model
330 "ChannelModel",
331 PointerValue(channelModel));
332
334
335 // set the beamforming vectors
336 DoBeamforming(txDev, txAntenna, rxDev);
337 DoBeamforming(rxDev, rxAntenna, txDev);
338
339 // create the tx power spectral density
340 Bands rbs;
341 double freqSubBand = frequency;
342 for (uint32_t n = 0; n < numRb; ++n)
343 {
344 BandInfo rb;
345 rb.fl = freqSubBand;
346 freqSubBand += subCarrierSpacing / 2;
347 rb.fc = freqSubBand;
348 freqSubBand += subCarrierSpacing / 2;
349 rb.fh = freqSubBand;
350 rbs.push_back(rb);
351 }
352 Ptr<SpectrumModel> spectrumModel = Create<SpectrumModel>(rbs);
353 Ptr<SpectrumValue> txPsd = Create<SpectrumValue>(spectrumModel);
355 double txPow_w = std::pow(10., (txPow_dbm - 30) / 10);
356 double txPowDens = (txPow_w / (numRb * subCarrierSpacing));
357 (*txPsd) = txPowDens;
358 txParams->psd = txPsd->Copy();
359
360 for (int i = 0; i < simTime / timeRes; i++)
361 {
362 ComputeSnrParams params{txMob, rxMob, txParams, noiseFigure, txAntenna, rxAntenna};
363 Simulator::Schedule(timeRes * i, &ComputeSnr, params);
364 }
365
366 // initialize the output file
367 std::ofstream f;
368 f.open("example-output.txt", std::ios::out);
369 f << "Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState SNR[dB] Pathloss[dB]"
370 << std::endl;
371 f.close();
372
373 // print the list of buildings to file
375
378 return 0;
379}
Class holding the azimuth and inclination angles of spherical coordinates.
Definition angles.h:107
AttributeValue implementation for Boolean.
Definition boolean.h:26
a 3d box
Definition box.h:24
double yMax
The y coordinate of the top bound of the box.
Definition box.h:105
double xMin
The x coordinate of the left bound of the box.
Definition box.h:99
double yMin
The y coordinate of the bottom bound of the box.
Definition box.h:103
double xMax
The x coordinate of the right bound of the box.
Definition box.h:101
static Iterator End()
static Iterator Begin()
static void Install(Ptr< Node > node)
Install the MobilityBuildingInfo to a node.
Parse command-line arguments.
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:31
Keep track of the current position and velocity of an object.
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.
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition node.cc:124
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition object.cc:298
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
AttributeValue implementation for Time.
Definition nstime.h:1432
Hold an unsigned integer type.
Definition uinteger.h:34
a (time, location) pair.
Definition waypoint.h:25
Waypoint-based mobility model.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
NodeContainer nodes
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)
params
Fit Fluctuating Two Ray model to the 3GPP TR 38.901 using the Anderson-Darling goodness-of-fit ##.
A structure that holds the parameters for the ComputeSnr function.
Ptr< PhasedArrayModel > txAntenna
the tx antenna array
Ptr< MobilityModel > rxMob
the rx mobility model
double noiseFigure
the noise figure in dB
Ptr< SpectrumSignalParameters > txParams
the params of the tx signal
Ptr< PhasedArrayModel > rxAntenna
the rx antenna array
Ptr< MobilityModel > txMob
the tx mobility model
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 log component
static void DoBeamforming(Ptr< NetDevice > thisDevice, Ptr< PhasedArrayModel > thisAntenna, Ptr< NetDevice > otherDevice)
Perform the beamforming using the DFT beamforming method.
static void ComputeSnr(const ComputeSnrParams &params)
Compute the average SNR.
void PrintGnuplottableBuildingListToFile(std::string filename)
Generates a GNU-plottable file representing the buildings deployed in the scenario.
static Ptr< ThreeGppSpectrumPropagationLossModel > m_spectrumLossModel
the SpectrumPropagationLossModel object