Loading...
Searching...
No Matches
satellite-wave-form-conf.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2013 Magister Solutions Ltd
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 * Author: Sami Rantanen <sami.rantanen@magister.fi>
19 */
20
22
25#include "satellite-utils.h"
26
27#include "ns3/boolean.h"
28#include "ns3/double.h"
29#include "ns3/enum.h"
30#include "ns3/log.h"
31#include "ns3/satellite-env-variables.h"
32#include "ns3/singleton.h"
33#include "ns3/uinteger.h"
34
35#include <algorithm>
36#include <cmath>
37#include <fstream>
38#include <iostream>
39#include <limits>
40#include <map>
41#include <sstream>
42#include <string>
43#include <utility>
44#include <vector>
45
46NS_LOG_COMPONENT_DEFINE("SatWaveformConf");
47
48namespace ns3
49{
50
52 : m_waveformId(0),
54 m_codingRate(0.0),
55 m_modCod(SatEnums::SAT_NONVALID_MODCOD),
60{
61 NS_ASSERT(false);
62}
63
65 uint32_t modulatedBits,
66 double codingRate,
68 uint32_t payloadBytes,
69 uint32_t lengthInSymbols,
70 uint32_t preambleLengthInSymbols)
71 : m_waveformId(wfId),
72 m_modulatedBits(modulatedBits),
73 m_codingRate(codingRate),
74 m_modCod(modcod),
75 m_payloadBytes(payloadBytes),
76 m_lengthInSymbols(lengthInSymbols),
77 m_preambleLengthInSymbols(preambleLengthInSymbols),
79{
80}
81
82uint32_t
84{
85 NS_LOG_FUNCTION(this);
86 return m_waveformId;
87}
88
91{
92 NS_LOG_FUNCTION(this);
93 return m_modCod;
94}
95
96uint32_t
98{
99 NS_LOG_FUNCTION(this);
100 return m_payloadBytes;
101}
102
103uint32_t
105{
106 NS_LOG_FUNCTION(this);
107 return m_lengthInSymbols;
108}
109
110uint32_t
112{
113 NS_LOG_FUNCTION(this);
115}
116
117Time
118SatWaveform::GetBurstDuration(double symbolRateInBaud) const
119{
120 NS_LOG_FUNCTION(this << symbolRateInBaud);
121 return Seconds(m_lengthInSymbols / symbolRateInBaud);
122}
123
124Time
125SatWaveform::GetPreambleDuration(double symbolRateInBaud) const
126{
127 NS_LOG_FUNCTION(this << symbolRateInBaud);
128 return Seconds(m_preambleLengthInSymbols / symbolRateInBaud);
129}
130
131double
132SatWaveform::GetSpectralEfficiency(double carrierBandwidthInHz, double symbolRateInBaud) const
133{
134 NS_LOG_FUNCTION(this << carrierBandwidthInHz << symbolRateInBaud);
136 (m_lengthInSymbols / symbolRateInBaud) / carrierBandwidthInHz;
137}
138
139double
140SatWaveform::GetThroughputInBitsPerSecond(double symbolRateInBaud) const
141{
142 NS_LOG_FUNCTION(this << symbolRateInBaud);
144 (m_lengthInSymbols / symbolRateInBaud);
145}
146
147double
148SatWaveform::GetCNoThreshold(double symbolRateInBaud) const
149{
150 NS_LOG_FUNCTION(this << symbolRateInBaud);
151
157 double cnoRequirement = m_ebnoRequirement * symbolRateInBaud * m_codingRate * m_modulatedBits;
158
159 return cnoRequirement;
160}
161
162void
163SatWaveform::SetEbNoRequirement(double ebnoRequirement)
164{
165 NS_LOG_FUNCTION(this << ebnoRequirement);
166 m_ebnoRequirement = ebnoRequirement;
167}
168
169void
170SatWaveform::Dump(double carrierBandwidthInHz, double symbolRateInBaud) const
171{
172 NS_LOG_FUNCTION(this << carrierBandwidthInHz << symbolRateInBaud);
173
174 std::cout << "ModulatedBits: " << m_modulatedBits << ", CodingRate: " << m_codingRate
175 << ", Payload: " << m_payloadBytes << ", BurstLength: " << m_lengthInSymbols
176 << ", EbNoRequirement: " << SatUtils::LinearToDb(m_ebnoRequirement)
177 << ", BurstDuration: " << GetBurstDuration(symbolRateInBaud)
178 << ", Throughput: " << GetThroughputInBitsPerSecond(symbolRateInBaud)
179 << ", SpectralEfficiency: "
180 << GetSpectralEfficiency(carrierBandwidthInHz, symbolRateInBaud)
181 << ", C/No threshold: " << SatUtils::LinearToDb(GetCNoThreshold(symbolRateInBaud))
182 << std::endl;
183}
184
185NS_OBJECT_ENSURE_REGISTERED(SatWaveformConf);
186
188 : m_waveforms(),
189 m_targetBLER(0.00001),
190 m_acmEnabled(false),
191 m_defaultWfId(3),
192 m_minWfId(0),
193 m_maxWfId(23),
194 m_burstLength(SatEnums::UNKNOWN_BURST)
195{
196 // default constructor should not be used
197 NS_ASSERT(false);
198}
199
200SatWaveformConf::SatWaveformConf(std::string directoryPathName)
201 : m_waveforms(),
202 m_targetBLER(0.00001),
203 m_acmEnabled(false),
204 m_defaultWfId(3),
205 m_minWfId(0),
206 m_maxWfId(23),
207 m_burstLength(SatEnums::UNKNOWN_BURST)
208{
209 NS_LOG_FUNCTION(this << directoryPathName);
210
211 if (!SatEnvVariables::GetInstance()->IsValidDirectory(directoryPathName))
212 {
213 NS_FATAL_ERROR("No such directory: " << directoryPathName);
214 }
215
216 std::string waveformsFilePathName = directoryPathName + "/waveforms.txt";
217 std::string defaultWaveform = directoryPathName + "/default_waveform.txt";
218
219 ReadFromFile(waveformsFilePathName);
220 ReadFromFileDefaultWaveform(defaultWaveform);
221}
222
223void
225{
226 NS_LOG_FUNCTION(this);
227
228 Object::NotifyConstructionCompleted();
229
230 switch (m_burstLength)
231 {
234 break;
237 break;
241 break;
242 default:
243 NS_FATAL_ERROR("Incorrect choice of burst length.");
244 }
245}
246
247TypeId
249{
250 static TypeId tid = TypeId("ns3::SatWaveformConf")
251 .SetParent<Object>()
252 .AddAttribute("TargetBLER",
253 "Block error rate target",
254 DoubleValue(0.00001),
255 MakeDoubleAccessor(&SatWaveformConf::m_targetBLER),
256 MakeDoubleChecker<double>())
257 .AddAttribute("AcmEnabled",
258 "Enable ACM",
259 BooleanValue(false),
260 MakeBooleanAccessor(&SatWaveformConf::m_acmEnabled),
261 MakeBooleanChecker())
262 .AddAttribute("BurstLength",
263 "Default burst length",
265 MakeEnumAccessor<SatEnums::SatWaveFormBurstLength_t>(
267 MakeEnumChecker(SatEnums::SHORT_BURST,
268 "ShortBurst",
270 "LongBurst",
272 "ShortAndLongBurst"))
273 .AddConstructor<SatWaveformConf>();
274 return tid;
275}
276
278{
279 NS_LOG_FUNCTION(this);
280}
281
282void
284{
285 NS_LOG_FUNCTION(this << filePathName);
286
287 // READ FROM THE SPECIFIED INPUT FILE
288 std::ifstream* ifs = new std::ifstream(filePathName.c_str(), std::ifstream::in);
289
290 if (!ifs->is_open())
291 {
292 // script might be launched by test.py, try a different base path
293 delete ifs;
294 filePathName = "../../" + filePathName;
295 ifs = new std::ifstream(filePathName.c_str(), std::ifstream::in);
296
297 if (!ifs->is_open())
298 {
299 NS_FATAL_ERROR("The file " << filePathName << " is not found.");
300 }
301 }
302
303 // Read line by line
304 std::string line;
305 std::getline(*ifs, line);
306 std::istringstream line_ss(line);
307 if (!(line_ss >> m_defaultWfId))
308 {
309 NS_FATAL_ERROR("SatWaveformConf::ReadFromFileDefaultWaveform - Waveform conf vector has "
310 "unexpected amount of elements!");
311 }
312}
313
314void
315SatWaveformConf::ReadFromFile(std::string filePathName)
316{
317 NS_LOG_FUNCTION(this << filePathName);
318
319 std::vector<uint32_t> wfIds;
320
321 // READ FROM THE SPECIFIED INPUT FILE
322 std::ifstream* ifs = new std::ifstream(filePathName.c_str(), std::ifstream::in);
323
324 if (!ifs->is_open())
325 {
326 // script might be launched by test.py, try a different base path
327 delete ifs;
328 filePathName = "../../" + filePathName;
329 ifs = new std::ifstream(filePathName.c_str(), std::ifstream::in);
330
331 if (!ifs->is_open())
332 {
333 NS_FATAL_ERROR("The file " << filePathName << " is not found.");
334 }
335 }
336
337 // Row vector containing the waveform information for a certain waveform index
338 std::vector<double> rowVector;
339
340 // Start conditions
341 int32_t wfIndex, modulatedBits, payloadBytes, durationInSymbols, preambleDurationInSymbols;
342 std::string sCodingRate;
343
344 // Read line by line
345 std::string line;
346
347 while (std::getline(*ifs, line))
348 {
349 std::istringstream line_ss(line);
350
351 // Unpack values
352 if (!(line_ss >> wfIndex >> modulatedBits >> sCodingRate >> payloadBytes >>
353 durationInSymbols))
354 {
355 NS_FATAL_ERROR("SatWaveformConf::ReadFromFile - Waveform conf vector has unexpected "
356 "amount of elements!");
357 }
358 // Try to unpack preambule duration
359 if (!(line_ss >> preambleDurationInSymbols))
360 {
361 preambleDurationInSymbols = 0;
362 }
363
364 // Store temporarily all wfIds
365 wfIds.push_back(wfIndex);
366
367 // Convert the coding rate fraction into double
368 std::istringstream ss(sCodingRate);
369 std::string token;
370 std::vector<uint32_t> output;
371
372 while (std::getline(ss, token, '/'))
373 {
374 uint32_t i;
375 std::stringstream s;
376 s.str(token);
377 s >> i;
378 output.push_back(i);
379 }
380
381 if (output.size() != 2)
382 {
383 NS_FATAL_ERROR("SatWaveformConf::ReadFromFile - Temp fraction vector has unexpected "
384 "amount of elements!");
385 }
386
387 double dCodingRate = double(output[0]) / output[1];
388
389 // Convert modulated bits and coding rate to MODCOD enum
390 SatEnums::SatModcod_t modcod = ConvertToModCod(modulatedBits, output[0], output[1]);
391
392 // Create new waveform and insert it to the waveform map
393 Ptr<SatWaveform> wf = Create<SatWaveform>(wfIndex,
394 modulatedBits,
395 dCodingRate,
396 modcod,
397 payloadBytes,
398 durationInSymbols,
399 preambleDurationInSymbols);
400 m_waveforms.insert(std::make_pair(wfIndex, wf));
401 }
402
403 ifs->close();
404 delete ifs;
405
406 // Note, currently we assume that the waveform ids are consecutive!
407 m_minWfId = *std::min_element(wfIds.begin(), wfIds.end());
408 m_maxWfId = *std::max_element(wfIds.begin(), wfIds.end());
409}
410
411void
412SatWaveformConf::InitializeEbNoRequirements(Ptr<SatLinkResultsRtn> linkResults)
413{
414 NS_LOG_FUNCTION(this);
415
416 for (std::map<uint32_t, Ptr<SatWaveform>>::iterator it = m_waveforms.begin();
417 it != m_waveforms.end();
418 ++it)
419 {
425 double ebnoRequirementDb = linkResults->GetEbNoDb(it->first, m_targetBLER);
426 it->second->SetEbNoRequirement(SatUtils::DbToLinear(ebnoRequirementDb));
427 }
428}
429
430Ptr<SatWaveform>
432{
433 NS_LOG_FUNCTION(this << wfId);
434
435 if (m_minWfId > wfId || wfId > m_maxWfId)
436 {
437 NS_FATAL_ERROR("SatWaveformConf::GetWaveform - unsupported waveform id: " << wfId);
438 }
439
440 return m_waveforms.at(wfId);
441}
442
443uint32_t
445{
446 NS_LOG_FUNCTION(this << m_defaultWfId);
447
449 {
450 NS_FATAL_ERROR(
451 "SatWaveformConf::GetDefaultWaveformId - unsupported waveform id: " << m_defaultWfId);
452 }
453
454 return m_defaultWfId;
455}
456
457bool
459 double symbolRateInBaud,
460 uint32_t& wfId,
461 double& cnoThreshold,
462 uint32_t burstLength) const
463{
464 NS_LOG_FUNCTION(this << cno << symbolRateInBaud << wfId << cnoThreshold << burstLength);
465
466 bool success = false;
467
468 // If ACM is disabled, return the default waveform
469 if (!m_acmEnabled || std::isnan(cno))
470 {
471 wfId = m_defaultWfId;
472 success = true;
473 return success;
474 }
475
476 // Return the waveform with best spectral efficiency
477 for (std::map<uint32_t, Ptr<SatWaveform>>::const_reverse_iterator rit = m_waveforms.rbegin();
478 rit != m_waveforms.rend();
479 ++rit)
480 {
481 if (rit->second->GetBurstLengthInSymbols() == burstLength)
482 {
483 double cnoThr = rit->second->GetCNoThreshold(symbolRateInBaud);
484 // The first waveform over the threshold
485 if (cnoThr <= cno)
486 {
487 wfId = rit->first;
488 cnoThreshold = cnoThr;
489 success = true;
490 break;
491 }
492 }
493 }
494
495 NS_LOG_INFO("Get best waveform in RTN link (ACM)! CNo: "
496 << SatUtils::LinearToDb(cno) << ", Symbol rate: " << symbolRateInBaud
497 << ", burst length: " << burstLength << ", WF: " << wfId
498 << ", CNo threshold: " << SatUtils::LinearToDb(cnoThreshold));
499
500 return success;
501}
502
503bool
504SatWaveformConf::GetMostRobustWaveformId(uint32_t& wfId, uint32_t burstLength) const
505{
506 NS_LOG_FUNCTION(this << burstLength);
507
508 bool found = false;
509
510 uint32_t payloadInBytes = std::numeric_limits<uint32_t>::max();
511
512 // find the waveform with the more robust waveform than previous one
513 for (std::map<uint32_t, Ptr<SatWaveform>>::const_reverse_iterator rit = m_waveforms.rbegin();
514 rit != m_waveforms.rend();
515 ++rit)
516 {
517 if (rit->second->GetBurstLengthInSymbols() == burstLength)
518 {
519 // The waveform more robust than previous one
520 if (rit->second->GetPayloadInBytes() < payloadInBytes)
521 {
522 payloadInBytes = rit->second->GetPayloadInBytes();
523 wfId = rit->first;
524 found = true;
525 }
526 }
527 }
528
529 return found;
530}
531
532void
533SatWaveformConf::Dump(double carrierBandwidthInHz, double symbolRateInBaud) const
534{
535 NS_LOG_FUNCTION(this << carrierBandwidthInHz << symbolRateInBaud);
536
537 for (std::map<uint32_t, Ptr<SatWaveform>>::const_iterator it = m_waveforms.begin();
538 it != m_waveforms.end();
539 ++it)
540 {
541 std::cout << "WaveformId: " << it->first << " ";
542 it->second->Dump(carrierBandwidthInHz, symbolRateInBaud);
543 }
544}
545
547SatWaveformConf::GetModCod(uint32_t wfId) const
548{
549 NS_LOG_FUNCTION(this << wfId);
550
551 if (m_minWfId > wfId || wfId > m_maxWfId)
552 {
553 NS_FATAL_ERROR("SatWaveformConf::GetModCod - unsupported waveform id: " << wfId);
554 }
555
556 std::map<uint32_t, Ptr<SatWaveform>>::const_iterator it = m_waveforms.find(wfId);
557
558 if (it != m_waveforms.end())
559 {
560 return m_waveforms.at(wfId)->GetModCod();
561 }
562 else
563 {
564 NS_FATAL_ERROR("Waveform id: " << wfId << " not found in the waveform container!");
565 }
566
568}
569
571SatWaveformConf::ConvertToModCod(uint32_t modulatedBits,
572 uint32_t codingRateNumerator,
573 uint32_t codingRateDenominator) const
574{
575 NS_LOG_FUNCTION(this << modulatedBits << codingRateNumerator << codingRateDenominator);
576
577 switch (modulatedBits)
578 {
579 // BPSK
580 case 1: {
581 if (codingRateNumerator == 1 && codingRateDenominator == 3)
582 {
584 }
585 else
586 {
587 NS_FATAL_ERROR("Unsupported coding rate numerator: "
588 << codingRateNumerator << ", denominator: " << codingRateDenominator);
589 }
590 break;
591 }
592 // QPSK
593 case 2: {
594 if (codingRateNumerator == 1 && codingRateDenominator == 3)
595 {
597 }
598 else if (codingRateNumerator == 1 && codingRateDenominator == 2)
599 {
601 }
602 else if (codingRateNumerator == 2 && codingRateDenominator == 3)
603 {
605 }
606 else if (codingRateNumerator == 3 && codingRateDenominator == 4)
607 {
609 }
610 else if (codingRateNumerator == 5 && codingRateDenominator == 6)
611 {
613 }
614 else
615 {
616 NS_FATAL_ERROR("Unsupported coding rate numerator: "
617 << codingRateNumerator << ", denominator: " << codingRateDenominator);
618 }
619 break;
620 }
621 // 8PSK
622 case 3: {
623 if (codingRateNumerator == 2 && codingRateDenominator == 3)
624 {
626 }
627 else if (codingRateNumerator == 3 && codingRateDenominator == 4)
628 {
630 }
631 else if (codingRateNumerator == 5 && codingRateDenominator == 6)
632 {
634 }
635 else
636 {
637 NS_FATAL_ERROR("Unsupported coding rate numerator: "
638 << codingRateNumerator << ", denominator: " << codingRateDenominator);
639 }
640 break;
641 }
642 // 16 QAM
643 case 4: {
644 if (codingRateNumerator == 3 && codingRateDenominator == 4)
645 {
647 }
648 else if (codingRateNumerator == 5 && codingRateDenominator == 6)
649 {
651 }
652 else
653 {
654 NS_FATAL_ERROR("Unsupported coding rate numerator: "
655 << codingRateNumerator << ", denominator: " << codingRateDenominator);
656 }
657
658 break;
659 }
660 default: {
661 NS_FATAL_ERROR("Unsupported modulated bits:" << modulatedBits);
662 break;
663 }
664 }
666}
667
668} // namespace ns3
SatEnums class is for simplifying the use of enumerators in the satellite module.
SatModcod_t
Modulation scheme and coding rate for DVB-S2.
static Ptr< SatEnvVariables > GetInstance()
static T DbToLinear(T db)
Converts decibels to linear.
static T LinearToDb(T linear)
Converts linear to decibels.
This class implements the available waveform configurations of DVB-RCS2 return link.
virtual ~SatWaveformConf()
Destructor for SatWaveformConf.
bool GetMostRobustWaveformId(uint32_t &wfId, uint32_t burstLength=SHORT_BURST_LENGTH) const
Get the most robust waveform id based payload of the waveform in bytes.
uint32_t m_defaultWfId
Default waveform id.
Ptr< SatWaveform > GetWaveform(uint32_t wfId) const
Get the details of a certain waveform.
void Dump(double carrierBandwidthInHz, double symbolRateInBaud) const
Dump the contents of the waveform.
void ReadFromFile(std::string filePathName)
Read the waveform table from a file.
SatEnums::SatWaveFormBurstLength_t m_burstLength
Burst length used.
bool GetBestWaveformId(double cno, double symbolRateInBaud, uint32_t &wfId, double &cnoThreshold, uint32_t burstLength=SHORT_BURST_LENGTH) const
Get the best waveform id based on UT's C/No and C/No thresholds.
std::map< uint32_t, Ptr< SatWaveform > > m_waveforms
Container of the waveforms.
static const uint32_t LONG_BURST_LENGTH
Static variable defining long burst length.
virtual void NotifyConstructionCompleted() override
Notifier called once the ObjectBase is fully constructed.
BurstLengthContainer_t m_supportedBurstLengthsInSymbols
Container to store supported burst lengths.
SatEnums::SatModcod_t GetModCod(uint32_t wfId) const
Get MODCOD enum corresponding to a waveform id.
void InitializeEbNoRequirements(Ptr< SatLinkResultsRtn > linkResults)
Initialize the Eb/No requirements of the waveforms based on the used return link results.
double m_targetBLER
Block error rate target for the waveforms.
bool m_acmEnabled
Flag to indicate whether ACM is enabled or disabled.
void ReadFromFileDefaultWaveform(std::string filePathName)
Read the default waveform ID from a file.
static const uint32_t SHORT_BURST_LENGTH
Static variable defining short burst length.
uint32_t GetDefaultWaveformId() const
Get default waveform id.
static TypeId GetTypeId(void)
Derived from Object.
SatWaveformConf()
Default constructor, which is not to be used.
SatEnums::SatModcod_t ConvertToModCod(uint32_t modulatedBits, uint32_t codingRateNumerator, uint32_t codingRateDenominator) const
Convert modulated bits and coding rate to a MODCOD enum.
uint32_t m_minWfId
Minimum and maximum waveform ids.
void SetEbNoRequirement(double ebnoRequirement)
Set the Eb/No requirement of the waveform in linear domain based on the used link results.
SatWaveform()
Default constructor for SatWaveform.
uint32_t m_payloadBytes
Payload in bytes.
uint32_t m_lengthInSymbols
Length of the burst in symbols.
double m_codingRate
Coding rate.
double m_ebnoRequirement
Eb/No threshold calculated with a certain BLER target from the link results.
uint32_t GetWaveformId() const
Get waveform id.
double GetCNoThreshold(double symbolRateInBaud) const
Get the C/No threshold of the waveform in linear domain.
SatEnums::SatModcod_t m_modCod
MODCOD enum.
uint32_t GetBurstLengthInSymbols() const
Get burst length of the waveform in symbols.
SatEnums::SatModcod_t GetModCod() const
Get MODCOD enum.
Time GetBurstDuration(double symbolRateInBaud) const
Get/calculate the burst duration of a waveform based on symbol rate.
Time GetPreambleDuration(double symbolRateInBaud) const
Get/calculate the preamble duration of a waveform based on symbol rate.
double GetSpectralEfficiency(double carrierBandwidthInHz, double symbolRateInBaud) const
Get/calculate the spectral efficiency of a waveform.
uint32_t GetPreambleLengthInSymbols() const
Get preamble length of the waveform in symbols.
uint32_t GetPayloadInBytes() const
Get payload of a waveform in bytes.
double GetThroughputInBitsPerSecond(double symbolRateInBaud) const
Get/calculate the throughput of a waveform based on symbol rate.
void Dump(double carrierBandwidthInHz, double symbolRateInBaud) const
Dump the contents of the waveform.
uint32_t m_waveformId
Id of this waveform.
uint32_t m_modulatedBits
Modulated bits QPSK = 2 8PSK = 3 16QAM = 4.
uint32_t m_preambleLengthInSymbols
Length of the preamble in symbols.
constexpr uint32_t BITS_PER_BYTE
Number of bits in a byte.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.