satellite-stats-antenna-gain-helper.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2018 CNES
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: Mathias Ettinger <mettinger@toulouse.viveris.com>
19  */
20 
22 
23 #include <ns3/boolean.h>
24 #include <ns3/callback.h>
25 #include <ns3/data-collection-object.h>
26 #include <ns3/distribution-collector.h>
27 #include <ns3/enum.h>
28 #include <ns3/log.h>
29 #include <ns3/magister-gnuplot-aggregator.h>
30 #include <ns3/multi-file-aggregator.h>
31 #include <ns3/node-container.h>
32 #include <ns3/nstime.h>
33 #include <ns3/probe.h>
34 #include <ns3/satellite-helper.h>
35 #include <ns3/satellite-ut-handover-module.h>
36 #include <ns3/scalar-collector.h>
37 #include <ns3/singleton.h>
38 #include <ns3/string.h>
39 #include <ns3/unit-conversion-collector.h>
40 
41 #include <sstream>
42 
43 NS_LOG_COMPONENT_DEFINE("SatStatsAntennaGainHelper");
44 
45 namespace ns3
46 {
47 
48 NS_OBJECT_ENSURE_REGISTERED(SatStatsAntennaGainHelper);
49 
51  : SatStatsHelper(satHelper),
52  m_averagingMode(false)
53 {
54  NS_LOG_FUNCTION(this << satHelper);
55 }
56 
58 {
59  NS_LOG_FUNCTION(this);
60 }
61 
62 TypeId
64 {
65  static TypeId tid =
66  TypeId("ns3::SatStatsAntennaGainHelper")
67  .SetParent<SatStatsHelper>()
68  .AddAttribute("AveragingMode",
69  "If true, all samples will be averaged before passed to aggregator. "
70  "Only affects histogram, PDF, and CDF output types.",
71  BooleanValue(false),
74  MakeBooleanChecker());
75  return tid;
76 }
77 
78 void
80 {
81  NS_LOG_FUNCTION(this << averagingMode);
82  m_averagingMode = averagingMode;
83 }
84 
85 bool
87 {
88  NS_LOG_FUNCTION(this);
89  return m_averagingMode;
90 }
91 
92 void
93 SatStatsAntennaGainHelper::AntennaGainCallback(std::string identifier, double gain)
94 {
95  std::stringstream ss(identifier);
96  uint32_t identifierNum;
97  if (!(ss >> identifierNum))
98  {
99  NS_FATAL_ERROR("Cannot convert '" << identifier << "' to number");
100  }
101  Ptr<DataCollectionObject> collector = m_terminalCollectors.Get(identifierNum);
102  NS_ASSERT_MSG(collector != nullptr,
103  "Unable to find collector with identifier " << identifierNum);
104 
105  switch (GetOutputType())
106  {
109  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
110  NS_ASSERT(c != nullptr);
111  c->TraceSinkDouble(0.0, gain);
112  break;
113  }
114 
117  Ptr<UnitConversionCollector> c = collector->GetObject<UnitConversionCollector>();
118  NS_ASSERT(c != nullptr);
119  c->TraceSinkDouble(0.0, gain);
120  break;
121  }
122 
129  if (m_averagingMode)
130  {
131  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
132  NS_ASSERT(c != nullptr);
133  c->TraceSinkDouble(0.0, gain);
134  }
135  else
136  {
137  Ptr<DistributionCollector> c = collector->GetObject<DistributionCollector>();
138  NS_ASSERT(c != nullptr);
139  c->TraceSinkDouble(0.0, gain);
140  }
141  break;
142 
143  default:
144  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
145  << " is not a valid output type for this statistics.");
146  break;
147  }
148 }
149 
150 void
152 {
153  NS_LOG_FUNCTION(this);
154 
155  switch (GetOutputType())
156  {
158  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
159  << " is not a valid output type for this statistics.");
160  break;
161 
163  // Setup aggregator.
164  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
165  "OutputFileName",
166  StringValue(GetOutputFileName()),
167  "MultiFileMode",
168  BooleanValue(false),
169  "EnableContextPrinting",
170  BooleanValue(true),
171  "GeneralHeading",
172  StringValue(GetIdentifierHeading("gain_db")));
173 
174  // Setup collectors.
175  m_terminalCollectors.SetType("ns3::ScalarCollector");
176  m_terminalCollectors.SetAttribute("InputDataType",
177  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
178  m_terminalCollectors.SetAttribute(
179  "OutputType",
180  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
182  m_terminalCollectors.ConnectToAggregator("Output",
183  m_aggregator,
184  &MultiFileAggregator::Write1d);
185  break;
186  }
187 
189  // Setup aggregator.
190  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
191  "OutputFileName",
192  StringValue(GetOutputFileName()),
193  "GeneralHeading",
194  StringValue(GetTimeHeading("gain_db")));
195 
196  // Setup collectors.
197  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
198  m_terminalCollectors.SetAttribute("ConversionType",
199  EnumValue(UnitConversionCollector::TRANSPARENT));
201  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
202  m_aggregator,
203  &MultiFileAggregator::Write2d);
204  break;
205  }
206 
210  if (m_averagingMode)
211  {
212  // Setup aggregator.
213  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
214  "OutputFileName",
215  StringValue(GetOutputFileName()),
216  "MultiFileMode",
217  BooleanValue(false),
218  "EnableContextPrinting",
219  BooleanValue(false),
220  "GeneralHeading",
221  StringValue(GetDistributionHeading("gain_db")));
222  Ptr<MultiFileAggregator> fileAggregator =
223  m_aggregator->GetObject<MultiFileAggregator>();
224  NS_ASSERT(fileAggregator != nullptr);
225 
226  // Setup the final-level collector.
227  m_averagingCollector = CreateObject<DistributionCollector>();
228  DistributionCollector::OutputType_t outputType =
229  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
231  {
232  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
233  }
235  {
236  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
237  }
238  m_averagingCollector->SetOutputType(outputType);
239  m_averagingCollector->SetName("0");
240  m_averagingCollector->TraceConnect(
241  "Output",
242  "0",
243  MakeCallback(&MultiFileAggregator::Write2d, fileAggregator));
244  m_averagingCollector->TraceConnect(
245  "OutputString",
246  "0",
247  MakeCallback(&MultiFileAggregator::AddContextHeading, fileAggregator));
248  m_averagingCollector->TraceConnect(
249  "Warning",
250  "0",
251  MakeCallback(&MultiFileAggregator::EnableContextWarning, fileAggregator));
252 
253  // Setup collectors.
254  m_terminalCollectors.SetType("ns3::ScalarCollector");
255  m_terminalCollectors.SetAttribute("InputDataType",
256  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
257  m_terminalCollectors.SetAttribute(
258  "OutputType",
259  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
261  Callback<void, double> callback =
262  MakeCallback(&DistributionCollector::TraceSinkDouble1, m_averagingCollector);
263  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
264  it != m_terminalCollectors.End();
265  ++it)
266  {
267  it->second->TraceConnectWithoutContext("Output", callback);
268  }
269  }
270  else
271  {
272  // Setup aggregator.
273  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
274  "OutputFileName",
275  StringValue(GetOutputFileName()),
276  "GeneralHeading",
277  StringValue(GetDistributionHeading("gain_db")));
278 
279  // Setup collectors.
280  m_terminalCollectors.SetType("ns3::DistributionCollector");
281  DistributionCollector::OutputType_t outputType =
282  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
284  {
285  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
286  }
288  {
289  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
290  }
291  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
293  m_terminalCollectors.ConnectToAggregator("Output",
294  m_aggregator,
295  &MultiFileAggregator::Write2d);
296  m_terminalCollectors.ConnectToAggregator("OutputString",
297  m_aggregator,
298  &MultiFileAggregator::AddContextHeading);
299  m_terminalCollectors.ConnectToAggregator("Warning",
300  m_aggregator,
301  &MultiFileAggregator::EnableContextWarning);
302  }
303 
304  break;
305  }
306 
309  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
310  << " is not a valid output type for this statistics.");
311  break;
312 
314  // Setup aggregator.
315  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
316  "OutputPath",
317  StringValue(GetOutputPath()),
318  "OutputFileName",
319  StringValue(GetName()));
320  Ptr<MagisterGnuplotAggregator> plotAggregator =
321  m_aggregator->GetObject<MagisterGnuplotAggregator>();
322  NS_ASSERT(plotAggregator != nullptr);
323  // plot->SetTitle ("");
324  plotAggregator->SetLegend("Time (in seconds)", "Antenna Gain (in dB)");
325  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
326 
327  // Setup collectors.
328  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
329  m_terminalCollectors.SetAttribute("ConversionType",
330  EnumValue(UnitConversionCollector::TRANSPARENT));
332  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
333  it != m_terminalCollectors.End();
334  ++it)
335  {
336  const std::string context = it->second->GetName();
337  plotAggregator->Add2dDataset(context, context);
338  }
339  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
340  m_aggregator,
341  &MagisterGnuplotAggregator::Write2d);
342  break;
343  }
344 
348  if (m_averagingMode)
349  {
350  // Setup aggregator.
351  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
352  "OutputPath",
353  StringValue(GetOutputPath()),
354  "OutputFileName",
355  StringValue(GetName()));
356  Ptr<MagisterGnuplotAggregator> plotAggregator =
357  m_aggregator->GetObject<MagisterGnuplotAggregator>();
358  NS_ASSERT(plotAggregator != nullptr);
359  // plot->SetTitle ("");
360  plotAggregator->SetLegend("Antenna gain (in dB)", "Frequency");
361  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
362  plotAggregator->Add2dDataset(GetName(), GetName());
364 
365  // Setup the final-level collector.
366  m_averagingCollector = CreateObject<DistributionCollector>();
367  DistributionCollector::OutputType_t outputType =
368  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
370  {
371  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
372  }
374  {
375  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
376  }
377  m_averagingCollector->SetOutputType(outputType);
378  m_averagingCollector->SetName("0");
379  m_averagingCollector->TraceConnect(
380  "Output",
381  GetName(),
382  MakeCallback(&MagisterGnuplotAggregator::Write2d, plotAggregator));
384 
385  // Setup collectors.
386  m_terminalCollectors.SetType("ns3::ScalarCollector");
387  m_terminalCollectors.SetAttribute("InputDataType",
388  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
389  m_terminalCollectors.SetAttribute(
390  "OutputType",
391  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
393  Callback<void, double> callback =
394  MakeCallback(&DistributionCollector::TraceSinkDouble1, m_averagingCollector);
395  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
396  it != m_terminalCollectors.End();
397  ++it)
398  {
399  it->second->TraceConnectWithoutContext("Output", callback);
400  }
401  }
402  else
403  {
404  // Setup aggregator.
405  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
406  "OutputPath",
407  StringValue(GetOutputPath()),
408  "OutputFileName",
409  StringValue(GetName()));
410  Ptr<MagisterGnuplotAggregator> plotAggregator =
411  m_aggregator->GetObject<MagisterGnuplotAggregator>();
412  NS_ASSERT(plotAggregator != nullptr);
413  // plot->SetTitle ("");
414  plotAggregator->SetLegend("Antenna gain (in dB)", "Frequency");
415  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
416 
417  // Setup collectors.
418  m_terminalCollectors.SetType("ns3::DistributionCollector");
419  DistributionCollector::OutputType_t outputType =
420  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
422  {
423  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
424  }
426  {
427  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
428  }
429  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
431  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
432  it != m_terminalCollectors.End();
433  ++it)
434  {
435  const std::string context = it->second->GetName();
436  plotAggregator->Add2dDataset(context, context);
437  }
438  m_terminalCollectors.ConnectToAggregator("Output",
439  m_aggregator,
440  &MagisterGnuplotAggregator::Write2d);
441  }
442 
443  break;
444  }
445 
446  default:
447  NS_FATAL_ERROR("SatStatsDelayHelper - Invalid output type");
448  break;
449  }
450 
451  // Setup probes and connect them to the collectors.
452  InstallProbes();
453 }
454 
455 void
457 {
458  NS_LOG_FUNCTION(this);
459 
460  Callback<void, std::string, double> callback =
462 
463  NodeContainer utUsers = GetSatHelper()->GetBeamHelper()->GetUtNodes();
464  for (NodeContainer::Iterator it = utUsers.Begin(); it != utUsers.End(); ++it)
465  {
466  Ptr<SatUtHandoverModule> hoModule = (*it)->GetObject<SatUtHandoverModule>();
467  if (!hoModule)
468  {
469  NS_LOG_INFO("UT " << *it << " does not check for antenna gain, bailing out.");
470  }
471  else
472  {
473  std::ostringstream oss;
474  oss << GetIdentifierForUt(*it);
475 
476  if (hoModule->TraceConnect("AntennaGainTrace", oss.str(), callback))
477  {
478  NS_LOG_INFO(this << " successfully connected with UT " << *it);
479  }
480  else
481  {
482  NS_LOG_WARN(this << " unable to connect to UT " << *it);
483  }
484  }
485  }
486 }
487 
488 } // namespace ns3
void AntennaGainCallback(std::string identifier, double gain)
Receive inputs from trace sources.
SatStatsAntennaGainHelper(Ptr< const SatHelper > satHelper)
void InstallProbes()
Set up several probes or other means of listeners and connect them to the collectors.
static TypeId GetTypeId()
inherited from ObjectBase base class
CollectorMap m_terminalCollectors
Maintains a list of collectors created by this helper.
Ptr< DataCollectionObject > m_aggregator
The aggregator created by this helper.
Ptr< DistributionCollector > m_averagingCollector
The final collector utilized in averaged output (histogram, PDF, and CDF).
void DoInstall()
Install the probes, collectors, and aggregators necessary to produce the statistics output.
Parent abstract class of all satellite statistics helpers.
Ptr< const SatHelper > GetSatHelper() const
static std::string GetOutputTypeName(OutputType_t outputType)
virtual std::string GetIdentifierHeading(std::string dataLabel) const
virtual std::string GetOutputPath() const
Ptr< DataCollectionObject > CreateAggregator(std::string aggregatorTypeId, std::string n1="", const AttributeValue &v1=EmptyAttributeValue(), std::string n2="", const AttributeValue &v2=EmptyAttributeValue(), std::string n3="", const AttributeValue &v3=EmptyAttributeValue(), std::string n4="", const AttributeValue &v4=EmptyAttributeValue(), std::string n5="", const AttributeValue &v5=EmptyAttributeValue())
Create the aggregator according to the output type.
virtual std::string GetOutputFileName() const
Compute the path and file name where statistics output should be written to.
uint32_t CreateCollectorPerIdentifier(CollectorMap &collectorMap) const
Create one collector instance for each identifier in the simulation.
OutputType_t GetOutputType() const
uint32_t GetIdentifierForUt(Ptr< Node > utNode) const
std::string GetName() const
virtual std::string GetTimeHeading(std::string dataLabel) const
virtual std::string GetDistributionHeading(std::string dataLabel) const
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.