A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tv-spectrum-transmitter-helper.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 University of Washington
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Benjamin Cizdziel <ben.cizdziel@gmail.com>
7 */
8
10
11#include <ns3/double.h>
12#include <ns3/geographic-positions.h>
13#include <ns3/isotropic-antenna-model.h>
14#include <ns3/log.h>
15#include <ns3/mobility-helper.h>
16#include <ns3/position-allocator.h>
17#include <ns3/uinteger.h>
18
19#include <cmath>
20#include <list>
21#include <vector>
22
23namespace ns3
24{
25
26NS_LOG_COMPONENT_DEFINE("TvSpectrumTransmitterHelper");
27
28/// NORTH AMERICA: 84 elements (index 0 - 83); valid channels = 2 - 83
30/// NORTH AMERICA start frequencies
31const double northAmericaStartFrequencies[84] = {
32 0, 0, 54e6, 60e6, 66e6, 76e6, 82e6, 174e6, 180e6, 186e6, 192e6, 198e6,
33 204e6, 210e6, 470e6, 476e6, 482e6, 488e6, 494e6, 500e6, 506e6, 512e6, 518e6, 524e6,
34 530e6, 536e6, 542e6, 548e6, 554e6, 560e6, 566e6, 572e6, 578e6, 584e6, 590e6, 596e6,
35 602e6, 608e6, 614e6, 620e6, 626e6, 632e6, 638e6, 644e6, 650e6, 656e6, 662e6, 668e6,
36 674e6, 680e6, 686e6, 692e6, 698e6, 704e6, 710e6, 716e6, 722e6, 728e6, 734e6, 740e6,
37 746e6, 752e6, 758e6, 764e6, 770e6, 776e6, 782e6, 788e6, 794e6, 800e6, 806e6, 812e6,
38 818e6, 824e6, 830e6, 836e6, 842e6, 848e6, 854e6, 860e6, 866e6, 872e6, 878e6, 884e6,
39};
40/// NORTH AMERICA end frequencies
41const double northAmericaEndFrequencies[84] = {
42 0, 0, 60e6, 66e6, 72e6, 82e6, 88e6, 180e6, 186e6, 192e6, 198e6, 204e6,
43 210e6, 216e6, 476e6, 482e6, 488e6, 494e6, 500e6, 506e6, 512e6, 518e6, 524e6, 530e6,
44 536e6, 542e6, 548e6, 554e6, 560e6, 566e6, 572e6, 578e6, 584e6, 590e6, 596e6, 602e6,
45 608e6, 614e6, 620e6, 626e6, 632e6, 638e6, 644e6, 650e6, 656e6, 662e6, 668e6, 674e6,
46 680e6, 686e6, 692e6, 698e6, 704e6, 710e6, 716e6, 722e6, 728e6, 734e6, 740e6, 746e6,
47 752e6, 758e6, 764e6, 770e6, 776e6, 782e6, 788e6, 794e6, 800e6, 806e6, 812e6, 818e6,
48 824e6, 830e6, 836e6, 842e6, 848e6, 854e6, 860e6, 866e6, 872e6, 878e6, 884e6, 890e6,
49};
50
51/// EUROPE: 70 elements (index 0 - 69); valid channels = 5 - 12, 21 - 69
52const int europeArrayLength = 70;
53/// EUROPE start frequencies
54const double europeStartFrequencies[70] = {
55 0, 0, 0, 0, 0, 174e6, 181e6, 188e6, 195e6, 202e6, 209e6, 216e6,
56 223e6, 0, 0, 0, 0, 0, 0, 0, 0, 470e6, 478e6, 486e6,
57 494e6, 502e6, 510e6, 518e6, 526e6, 534e6, 542e6, 550e6, 558e6, 566e6, 574e6, 582e6,
58 590e6, 598e6, 606e6, 614e6, 622e6, 630e6, 638e6, 646e6, 654e6, 662e6, 670e6, 678e6,
59 686e6, 694e6, 702e6, 710e6, 718e6, 726e6, 734e6, 742e6, 750e6, 758e6, 766e6, 774e6,
60 782e6, 790e6, 798e6, 806e6, 814e6, 822e6, 830e6, 838e6, 846e6, 854e6,
61};
62/// EUROPE end frequencies
63const double europeEndFrequencies[70] = {
64 0, 0, 0, 0, 0, 181e6, 188e6, 195e6, 202e6, 209e6, 216e6, 223e6,
65 230e6, 0, 0, 0, 0, 0, 0, 0, 0, 478e6, 486e6, 494e6,
66 502e6, 510e6, 518e6, 526e6, 534e6, 542e6, 550e6, 558e6, 566e6, 574e6, 582e6, 590e6,
67 598e6, 606e6, 614e6, 622e6, 630e6, 638e6, 646e6, 654e6, 662e6, 670e6, 678e6, 686e6,
68 694e6, 702e6, 710e6, 718e6, 726e6, 734e6, 742e6, 750e6, 758e6, 766e6, 774e6, 782e6,
69 790e6, 798e6, 806e6, 814e6, 822e6, 830e6, 838e6, 846e6, 854e6, 862e6,
70};
71
72/// JAPAN: 63 elements (index 0 - 62); valid channels = 1 - 62
73const int japanArrayLength = 63;
74/// JAPAN start frequencies
75const double japanStartFrequencies[63] = {
76 0, 90e6, 96e6, 102e6, 170e6, 176e6, 182e6, 188e6, 192e6, 198e6, 204e6, 210e6, 216e6,
77 470e6, 476e6, 482e6, 488e6, 494e6, 500e6, 506e6, 512e6, 518e6, 524e6, 530e6, 536e6, 542e6,
78 548e6, 554e6, 560e6, 566e6, 572e6, 578e6, 584e6, 590e6, 596e6, 602e6, 608e6, 614e6, 620e6,
79 626e6, 632e6, 638e6, 644e6, 650e6, 656e6, 662e6, 668e6, 674e6, 680e6, 686e6, 692e6, 698e6,
80 704e6, 710e6, 716e6, 722e6, 728e6, 734e6, 740e6, 746e6, 752e6, 758e6, 764e6,
81};
82/// JAPAN end frequencies
83const double japanEndFrequencies[63] = {
84 0, 96e6, 102e6, 108e6, 176e6, 182e6, 188e6, 194e6, 198e6, 204e6, 210e6, 216e6, 222e6,
85 476e6, 482e6, 488e6, 494e6, 500e6, 506e6, 512e6, 518e6, 524e6, 530e6, 536e6, 542e6, 548e6,
86 554e6, 560e6, 566e6, 572e6, 578e6, 584e6, 590e6, 596e6, 602e6, 608e6, 614e6, 620e6, 626e6,
87 632e6, 638e6, 644e6, 650e6, 656e6, 662e6, 668e6, 674e6, 680e6, 686e6, 692e6, 698e6, 704e6,
88 710e6, 716e6, 722e6, 728e6, 734e6, 740e6, 746e6, 752e6, 758e6, 764e6, 770e6,
89};
90
92 : m_channel(nullptr),
94{
95 NS_LOG_FUNCTION(this);
96 m_factory.SetTypeId("ns3::TvSpectrumTransmitter");
97}
98
105
106void
112
113void
115{
116 m_factory.Set(name, val);
117}
118
121{
122 NS_LOG_FUNCTION(this);
123 NetDeviceContainer devCont;
124 // iterate over node container to make one transmitter for each given node
125 for (auto i = nodeCont.Begin(); i != nodeCont.End(); ++i)
126 {
127 Ptr<Node> node = *i;
129 phy->CreateTvPsd();
131 NS_ASSERT(phy);
132 dev->SetPhy(phy);
133 NS_ASSERT(node);
134 phy->SetMobility(node->GetObject<MobilityModel>());
135 NS_ASSERT(dev);
136 phy->SetDevice(dev);
138 phy->SetChannel(m_channel);
139 dev->SetChannel(m_channel);
140 node->AddDevice(dev);
141 devCont.Add(dev);
142 phy->Start();
143 }
144 return devCont;
145}
146
148TvSpectrumTransmitterHelper::Install(NodeContainer nodeCont, Region region, uint16_t channelNumber)
149{
150 NS_LOG_FUNCTION(this);
151 NetDeviceContainer devCont;
152 double startFrequency;
153 double channelBandwidth;
154 if (region == REGION_NORTH_AMERICA)
155 {
157 "channel number " << channelNumber << " does not exist for this region");
159 "channel number " << channelNumber << " does not exist for this region");
160 startFrequency = northAmericaStartFrequencies[channelNumber];
161 channelBandwidth =
162 northAmericaEndFrequencies[channelNumber] - northAmericaStartFrequencies[channelNumber];
163 }
164 else if (region == REGION_EUROPE)
165 {
166 NS_ASSERT_MSG(channelNumber < europeArrayLength,
167 "channel number " << channelNumber << " does not exist for this region");
168 NS_ASSERT_MSG(europeStartFrequencies[channelNumber] != 0,
169 "channel number " << channelNumber << " does not exist for this region");
170 startFrequency = europeStartFrequencies[channelNumber];
171 channelBandwidth =
172 europeEndFrequencies[channelNumber] - europeStartFrequencies[channelNumber];
173 }
174 else if (region == REGION_JAPAN)
175 {
176 NS_ASSERT_MSG(channelNumber < japanArrayLength,
177 "channel number " << channelNumber << " does not exist for this region");
178 NS_ASSERT_MSG(japanStartFrequencies[channelNumber] != 0,
179 "channel number " << channelNumber << " does not exist for this region");
180 startFrequency = japanStartFrequencies[channelNumber];
181 channelBandwidth =
182 japanEndFrequencies[channelNumber] - japanStartFrequencies[channelNumber];
183 }
184 // iterate over node container to make one transmitter for each given node
185 for (auto i = nodeCont.Begin(); i != nodeCont.End(); ++i)
186 {
187 Ptr<Node> node = *i;
189 phy->SetAttribute("StartFrequency", DoubleValue(startFrequency));
190 phy->SetAttribute("ChannelBandwidth", DoubleValue(channelBandwidth));
191 phy->CreateTvPsd();
193 NS_ASSERT(phy);
194 dev->SetPhy(phy);
195 NS_ASSERT(node);
196 phy->SetMobility(node->GetObject<MobilityModel>());
197 NS_ASSERT(dev);
198 phy->SetDevice(dev);
200 phy->SetChannel(m_channel);
201 dev->SetChannel(m_channel);
202 node->AddDevice(dev);
203 devCont.Add(dev);
204 phy->Start();
205 }
206 return devCont;
207}
208
211{
212 NS_LOG_FUNCTION(this);
213 NetDeviceContainer devCont;
214 int index = 0;
215 DoubleValue startFrequency;
216 DoubleValue channelBandwidth;
217 // iterate over node container to make one transmitter for each given node
218 for (auto i = nodeCont.Begin(); i != nodeCont.End(); ++i)
219 {
220 Ptr<Node> node = *i;
222 phy->GetAttribute("StartFrequency", startFrequency);
223 phy->GetAttribute("ChannelBandwidth", channelBandwidth);
224 phy->SetAttribute("StartFrequency",
225 DoubleValue(startFrequency.Get() + (index * channelBandwidth.Get())));
226 phy->CreateTvPsd();
228 NS_ASSERT(phy);
229 dev->SetPhy(phy);
230 NS_ASSERT(node);
231 phy->SetMobility(node->GetObject<MobilityModel>());
232 NS_ASSERT(dev);
233 phy->SetDevice(dev);
235 phy->SetChannel(m_channel);
236 dev->SetChannel(m_channel);
237 node->AddDevice(dev);
238 devCont.Add(dev);
239 phy->Start();
240 index++;
241 }
242 return devCont;
243}
244
247 Region region,
248 uint16_t channelNumber)
249{
250 NS_LOG_FUNCTION(this);
251 NetDeviceContainer devCont;
252 double startFrequency;
253 double channelBandwidth;
254 uint16_t currChannelNumber;
255 int index = 0;
256 // iterate over node container to make one transmitter for each given node
257 for (auto i = nodeCont.Begin(); i != nodeCont.End(); ++i)
258 {
259 currChannelNumber = channelNumber + index;
260 if (region == REGION_NORTH_AMERICA)
261 {
262 NS_ASSERT_MSG(currChannelNumber < northAmericaArrayLength,
263 "channel number " << currChannelNumber
264 << " does not exist for this region");
265 NS_ASSERT_MSG(northAmericaStartFrequencies[currChannelNumber] != 0,
266 "channel number " << currChannelNumber
267 << " does not exist for this region");
268 startFrequency = northAmericaStartFrequencies[currChannelNumber];
269 channelBandwidth = northAmericaEndFrequencies[currChannelNumber] -
270 northAmericaStartFrequencies[currChannelNumber];
271 }
272 else if (region == REGION_EUROPE)
273 {
274 NS_ASSERT_MSG(currChannelNumber < europeArrayLength,
275 "channel number " << currChannelNumber
276 << " does not exist for this region");
277 NS_ASSERT_MSG(europeStartFrequencies[currChannelNumber] != 0,
278 "channel number " << currChannelNumber
279 << " does not exist for this region");
280 startFrequency = europeStartFrequencies[currChannelNumber];
281 channelBandwidth =
282 europeEndFrequencies[currChannelNumber] - europeStartFrequencies[currChannelNumber];
283 }
284 else if (region == REGION_JAPAN)
285 {
286 NS_ASSERT_MSG(currChannelNumber < japanArrayLength,
287 "channel number " << currChannelNumber
288 << " does not exist for this region");
289 NS_ASSERT_MSG(japanStartFrequencies[currChannelNumber] != 0,
290 "channel number " << currChannelNumber
291 << " does not exist for this region");
292 startFrequency = japanStartFrequencies[currChannelNumber];
293 channelBandwidth =
294 japanEndFrequencies[currChannelNumber] - japanStartFrequencies[currChannelNumber];
295 }
296 Ptr<Node> node = *i;
298 phy->SetAttribute("StartFrequency", DoubleValue(startFrequency));
299 phy->SetAttribute("ChannelBandwidth", DoubleValue(channelBandwidth));
300 phy->CreateTvPsd();
302 NS_ASSERT(phy);
303 dev->SetPhy(phy);
304 NS_ASSERT(node);
305 phy->SetMobility(node->GetObject<MobilityModel>());
306 NS_ASSERT(dev);
307 phy->SetDevice(dev);
309 phy->SetChannel(m_channel);
310 dev->SetChannel(m_channel);
311 node->AddDevice(dev);
312 devCont.Add(dev);
313 phy->Start();
314 index++;
315 }
316 return devCont;
317}
318
319int64_t
321{
322 m_uniRand->SetStream(streamNum);
323 return 1;
324}
325
326void
328 Density density,
329 double originLatitude,
330 double originLongitude,
331 double maxAltitude,
332 double maxRadius)
333{
334 NS_LOG_FUNCTION(this);
335 std::list<int> transmitterIndicesToCreate;
336 if (region == REGION_NORTH_AMERICA)
337 {
338 transmitterIndicesToCreate =
341 density);
342 }
343 else if (region == REGION_EUROPE)
344 {
345 transmitterIndicesToCreate =
347 }
348 else if (region == REGION_JAPAN)
349 {
350 transmitterIndicesToCreate =
352 }
353 std::list<Vector> tvTransmitterLocations =
355 originLatitude,
356 originLongitude,
357 maxAltitude,
358 transmitterIndicesToCreate.size(),
359 maxRadius,
360 m_uniRand);
361 InstallRandomRegionalTransmitters(region, transmitterIndicesToCreate, tvTransmitterLocations);
362}
363
364std::list<int>
366 const int startFrequenciesLength,
367 Density density)
368{
369 std::vector<double> startFreqVector; // stores all non-zero start frequencies
370 for (int i = 0; i < startFrequenciesLength; i++)
371 {
372 double element = startFrequencies[i];
373 // add all non-zero frequencies to vector (0 means unused channel)
374 if (element != 0)
375 {
376 startFreqVector.push_back(element);
377 }
378 }
379
380 // randomly generate number of transmitters to create based on density
381 uint32_t freqVectorSize = startFreqVector.size();
382 int randNumTransmitters = GetRandomNumTransmitters(density, freqVectorSize);
383
384 // stores start frequencies that transmitters will be created to transmit
385 std::vector<double> transmitterStartFreqsToCreate;
386 for (int i = 0; i < randNumTransmitters; i++)
387 {
388 // get random index from start frequency vector
389 uint32_t randIndex = m_uniRand->GetInteger(0, startFreqVector.size() - 1);
390 // add start frequency corresponding to random index to vector
391 transmitterStartFreqsToCreate.push_back(startFreqVector[randIndex]);
392 // remove selected start frequency from vector so it is not selected again
393 startFreqVector.erase(startFreqVector.begin() + randIndex);
394 }
395
396 // find indices on startFrequencies[] containing each start frequency that is
397 // selected to be transmitted and add to list
398 std::list<int> transmitterIndicesToCreate;
399 for (int i = 0; i < (int)transmitterStartFreqsToCreate.size(); i++)
400 {
401 for (int channelNumberIndex = 0; channelNumberIndex < startFrequenciesLength;
402 channelNumberIndex++)
403 {
404 if (startFrequencies[channelNumberIndex] == transmitterStartFreqsToCreate[i])
405 {
406 transmitterIndicesToCreate.push_back(channelNumberIndex);
407 break;
408 }
409 }
410 }
411 return transmitterIndicesToCreate;
412}
413
414int
416{
417 int numTransmitters;
418 if (density == DENSITY_LOW)
419 {
420 numTransmitters = m_uniRand->GetInteger(1, ceil(0.33 * numChannels));
421 }
422 else if (density == DENSITY_MEDIUM)
423 {
424 numTransmitters =
425 m_uniRand->GetInteger(ceil(0.33 * numChannels) + 1, ceil(0.66 * numChannels));
426 }
427 else
428 {
429 numTransmitters = m_uniRand->GetInteger(ceil(0.66 * numChannels) + 1, numChannels);
430 }
431 return numTransmitters;
432}
433
434void
436 Region region,
437 std::list<int> transmitterIndicesToCreate,
438 std::list<Vector> transmitterLocations)
439{
440 int numTransmitters = (int)transmitterIndicesToCreate.size();
441 for (int transNum = 0; transNum < numTransmitters; transNum++)
442 {
444 // add generated coordinate point to node position
445 nodePosition->Add(transmitterLocations.front());
446 MobilityHelper mobility;
447 mobility.SetPositionAllocator(nodePosition);
448 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
449 NodeContainer tvNode; // contains position of transmitter to be created
450 tvNode.Create(1);
451 mobility.Install(tvNode);
452 // set channel number for this transmitter
453 auto channelNumber = (uint16_t)transmitterIndicesToCreate.front();
454 Install(tvNode, region, channelNumber); // install tv transmitter
455 transmitterLocations.pop_front(); // remove created transmitter location
456 transmitterIndicesToCreate.pop_front(); // remove created transmitter index
457 }
458}
459
460} // namespace ns3
Hold a value for an Attribute.
Definition attribute.h:59
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
double Get() const
Definition double.cc:26
static std::list< Vector > RandCartesianPointsAroundGeographicPoint(double originLatitude, double originLongitude, double maxAltitude, int numPoints, double maxDistFromOrigin, Ptr< UniformRandomVariable > uniRand)
Generates uniformly distributed random points (in ECEF Cartesian coordinates) within a given altitude...
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
holds a vector of ns3::NetDevice pointers
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
keep track of a set of node pointers.
Iterator End() const
Get an iterator which indicates past-the-last Node in the container.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Iterator Begin() const
Get an iterator which refers to the first Node in the container.
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void Set(const std::string &name, const AttributeValue &value, Args &&... args)
Set an attribute to be set during construction.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
Smart pointer class similar to boost::intrusive_ptr.
std::list< int > GenerateRegionalTransmitterIndices(const double startFrequencies[], const int startFrequenciesLength, Density density)
Generates random indices of given region frequency array (ignoring indices referring to invalid chann...
void SetChannel(Ptr< SpectrumChannel > c)
Set the spectrum channel for the device(s) to transmit on.
NetDeviceContainer InstallAdjacent(NodeContainer nodes)
Set up and start the TV Transmitter's transmission on the spectrum channel.
Density
density of location that TV transmitters are being set up in
void InstallRandomRegionalTransmitters(Region region, std::list< int > transmitterIndicesToCreate, std::list< Vector > transmitterLocations)
Installs each randomly generated regional TV transmitter.
Region
geographical region that TV transmitters are being set up in
int GetRandomNumTransmitters(Density density, uint32_t numChannels)
Randomly generates the number of TV transmitters to be created based on given density and number of p...
Ptr< UniformRandomVariable > m_uniRand
Object to generate uniform random numbers.
int64_t AssignStreams(int64_t streamNum)
Assigns the stream number for the uniform random number generator to use.
ObjectFactory m_factory
Object factory for attribute setting.
void CreateRegionalTvTransmitters(Region region, Density density, double originLatitude, double originLongitude, double maxAltitude, double maxRadius)
Generates and installs (starts transmission on the spectrum channel) a random number of TV transmitte...
void SetAttribute(std::string name, const AttributeValue &val)
Set attribute for each TvSpectrumTransmitter instance to be created.
NetDeviceContainer Install(NodeContainer nodes)
Set up and start the TV Transmitter's transmission on the spectrum channel.
Ptr< SpectrumChannel > m_channel
Pointer to spectrum channel object.
SpectrumPhy implementation that creates a customizable TV transmitter which transmits a PSD spectrum ...
The uniform distribution Random Number Generator (RNG).
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Every class exported by the ns3 library is enclosed in the ns3 namespace.
const double northAmericaEndFrequencies[84]
NORTH AMERICA end frequencies.
const int japanArrayLength
JAPAN: 63 elements (index 0 - 62); valid channels = 1 - 62.
const double europeEndFrequencies[70]
EUROPE end frequencies.
const int northAmericaArrayLength
NORTH AMERICA: 84 elements (index 0 - 83); valid channels = 2 - 83.
const double japanStartFrequencies[63]
JAPAN start frequencies.
const double europeStartFrequencies[70]
EUROPE start frequencies.
const double japanEndFrequencies[63]
JAPAN end frequencies.
const double northAmericaStartFrequencies[84]
NORTH AMERICA start frequencies.
const int europeArrayLength
EUROPE: 70 elements (index 0 - 69); valid channels = 5 - 12, 21 - 69.