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-handover-module.h>
35 #include <ns3/satellite-helper.h>
36 #include <ns3/satellite-topology.h>
37 #include <ns3/scalar-collector.h>
38 #include <ns3/singleton.h>
39 #include <ns3/string.h>
40 #include <ns3/unit-conversion-collector.h>
41 
42 #include <sstream>
43 #include <string>
44 
45 NS_LOG_COMPONENT_DEFINE("SatStatsAntennaGainHelper");
46 
47 namespace ns3
48 {
49 
50 NS_OBJECT_ENSURE_REGISTERED(SatStatsAntennaGainHelper);
51 
53  : SatStatsHelper(satHelper),
54  m_averagingMode(false)
55 {
56  NS_LOG_FUNCTION(this << satHelper);
57 }
58 
60 {
61  NS_LOG_FUNCTION(this);
62 }
63 
64 TypeId
66 {
67  static TypeId tid =
68  TypeId("ns3::SatStatsAntennaGainHelper")
69  .SetParent<SatStatsHelper>()
70  .AddAttribute("AveragingMode",
71  "If true, all samples will be averaged before passed to aggregator. "
72  "Only affects histogram, PDF, and CDF output types.",
73  BooleanValue(false),
76  MakeBooleanChecker());
77  return tid;
78 }
79 
80 void
82 {
83  NS_LOG_FUNCTION(this << averagingMode);
84  m_averagingMode = averagingMode;
85 }
86 
87 bool
89 {
90  NS_LOG_FUNCTION(this);
91  return m_averagingMode;
92 }
93 
94 void
95 SatStatsAntennaGainHelper::AntennaGainCallback(std::string identifier, double gain)
96 {
97  std::stringstream ss(identifier);
98  uint32_t identifierNum;
99  if (!(ss >> identifierNum))
100  {
101  NS_FATAL_ERROR("Cannot convert '" << identifier << "' to number");
102  }
103  Ptr<DataCollectionObject> collector = m_terminalCollectors.Get(identifierNum);
104  NS_ASSERT_MSG(collector != nullptr,
105  "Unable to find collector with identifier " << identifierNum);
106 
107  switch (GetOutputType())
108  {
111  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
112  NS_ASSERT(c != nullptr);
113  c->TraceSinkDouble(0.0, gain);
114  break;
115  }
116 
119  Ptr<UnitConversionCollector> c = collector->GetObject<UnitConversionCollector>();
120  NS_ASSERT(c != nullptr);
121  c->TraceSinkDouble(0.0, gain);
122  break;
123  }
124 
131  if (m_averagingMode)
132  {
133  Ptr<ScalarCollector> c = collector->GetObject<ScalarCollector>();
134  NS_ASSERT(c != nullptr);
135  c->TraceSinkDouble(0.0, gain);
136  }
137  else
138  {
139  Ptr<DistributionCollector> c = collector->GetObject<DistributionCollector>();
140  NS_ASSERT(c != nullptr);
141  c->TraceSinkDouble(0.0, gain);
142  }
143  break;
144 
145  default:
146  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
147  << " is not a valid output type for this statistics.");
148  break;
149  }
150 }
151 
152 void
154 {
155  NS_LOG_FUNCTION(this);
156 
157  switch (GetOutputType())
158  {
160  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
161  << " is not a valid output type for this statistics.");
162  break;
163 
165  // Setup aggregator.
166  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
167  "OutputFileName",
168  StringValue(GetOutputFileName()),
169  "MultiFileMode",
170  BooleanValue(false),
171  "EnableContextPrinting",
172  BooleanValue(true),
173  "GeneralHeading",
174  StringValue(GetIdentifierHeading("gain_db")));
175 
176  // Setup collectors.
177  m_terminalCollectors.SetType("ns3::ScalarCollector");
178  m_terminalCollectors.SetAttribute("InputDataType",
179  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
180  m_terminalCollectors.SetAttribute(
181  "OutputType",
182  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
184  m_terminalCollectors.ConnectToAggregator("Output",
185  m_aggregator,
186  &MultiFileAggregator::Write1d);
187  break;
188  }
189 
191  // Setup aggregator.
192  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
193  "OutputFileName",
194  StringValue(GetOutputFileName()),
195  "GeneralHeading",
196  StringValue(GetTimeHeading("gain_db")));
197 
198  // Setup collectors.
199  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
200  m_terminalCollectors.SetAttribute("ConversionType",
201  EnumValue(UnitConversionCollector::TRANSPARENT));
203  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
204  m_aggregator,
205  &MultiFileAggregator::Write2d);
206  break;
207  }
208 
212  if (m_averagingMode)
213  {
214  // Setup aggregator.
215  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
216  "OutputFileName",
217  StringValue(GetOutputFileName()),
218  "MultiFileMode",
219  BooleanValue(false),
220  "EnableContextPrinting",
221  BooleanValue(false),
222  "GeneralHeading",
223  StringValue(GetDistributionHeading("gain_db")));
224  Ptr<MultiFileAggregator> fileAggregator =
225  m_aggregator->GetObject<MultiFileAggregator>();
226  NS_ASSERT(fileAggregator != nullptr);
227 
228  // Setup the final-level collector.
229  m_averagingCollector = CreateObject<DistributionCollector>();
230  DistributionCollector::OutputType_t outputType =
231  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
233  {
234  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
235  }
237  {
238  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
239  }
240  m_averagingCollector->SetOutputType(outputType);
241  m_averagingCollector->SetName("0");
242  m_averagingCollector->TraceConnect(
243  "Output",
244  "0",
245  MakeCallback(&MultiFileAggregator::Write2d, fileAggregator));
246  m_averagingCollector->TraceConnect(
247  "OutputString",
248  "0",
249  MakeCallback(&MultiFileAggregator::AddContextHeading, fileAggregator));
250  m_averagingCollector->TraceConnect(
251  "Warning",
252  "0",
253  MakeCallback(&MultiFileAggregator::EnableContextWarning, fileAggregator));
254 
255  // Setup collectors.
256  m_terminalCollectors.SetType("ns3::ScalarCollector");
257  m_terminalCollectors.SetAttribute("InputDataType",
258  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
259  m_terminalCollectors.SetAttribute(
260  "OutputType",
261  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
263  Callback<void, double> callback =
264  MakeCallback(&DistributionCollector::TraceSinkDouble1, m_averagingCollector);
265  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
266  it != m_terminalCollectors.End();
267  ++it)
268  {
269  it->second->TraceConnectWithoutContext("Output", callback);
270  }
271  }
272  else
273  {
274  // Setup aggregator.
275  m_aggregator = CreateAggregator("ns3::MultiFileAggregator",
276  "OutputFileName",
277  StringValue(GetOutputFileName()),
278  "GeneralHeading",
279  StringValue(GetDistributionHeading("gain_db")));
280 
281  // Setup collectors.
282  m_terminalCollectors.SetType("ns3::DistributionCollector");
283  DistributionCollector::OutputType_t outputType =
284  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
286  {
287  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
288  }
290  {
291  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
292  }
293  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
295  m_terminalCollectors.ConnectToAggregator("Output",
296  m_aggregator,
297  &MultiFileAggregator::Write2d);
298  m_terminalCollectors.ConnectToAggregator("OutputString",
299  m_aggregator,
300  &MultiFileAggregator::AddContextHeading);
301  m_terminalCollectors.ConnectToAggregator("Warning",
302  m_aggregator,
303  &MultiFileAggregator::EnableContextWarning);
304  }
305 
306  break;
307  }
308 
311  NS_FATAL_ERROR(GetOutputTypeName(GetOutputType())
312  << " is not a valid output type for this statistics.");
313  break;
314 
316  // Setup aggregator.
317  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
318  "OutputPath",
319  StringValue(GetOutputPath()),
320  "OutputFileName",
321  StringValue(GetName()));
322  Ptr<MagisterGnuplotAggregator> plotAggregator =
323  m_aggregator->GetObject<MagisterGnuplotAggregator>();
324  NS_ASSERT(plotAggregator != nullptr);
325  // plot->SetTitle ("");
326  plotAggregator->SetLegend("Time (in seconds)", "Antenna Gain (in dB)");
327  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
328 
329  // Setup collectors.
330  m_terminalCollectors.SetType("ns3::UnitConversionCollector");
331  m_terminalCollectors.SetAttribute("ConversionType",
332  EnumValue(UnitConversionCollector::TRANSPARENT));
334  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
335  it != m_terminalCollectors.End();
336  ++it)
337  {
338  const std::string context = it->second->GetName();
339  plotAggregator->Add2dDataset(context, context);
340  }
341  m_terminalCollectors.ConnectToAggregator("OutputTimeValue",
342  m_aggregator,
343  &MagisterGnuplotAggregator::Write2d);
344  break;
345  }
346 
350  if (m_averagingMode)
351  {
352  // Setup aggregator.
353  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
354  "OutputPath",
355  StringValue(GetOutputPath()),
356  "OutputFileName",
357  StringValue(GetName()));
358  Ptr<MagisterGnuplotAggregator> plotAggregator =
359  m_aggregator->GetObject<MagisterGnuplotAggregator>();
360  NS_ASSERT(plotAggregator != nullptr);
361  // plot->SetTitle ("");
362  plotAggregator->SetLegend("Antenna gain (in dB)", "Frequency");
363  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
364  plotAggregator->Add2dDataset(GetName(), GetName());
366 
367  // Setup the final-level collector.
368  m_averagingCollector = CreateObject<DistributionCollector>();
369  DistributionCollector::OutputType_t outputType =
370  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
372  {
373  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
374  }
376  {
377  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
378  }
379  m_averagingCollector->SetOutputType(outputType);
380  m_averagingCollector->SetName("0");
381  m_averagingCollector->TraceConnect(
382  "Output",
383  GetName(),
384  MakeCallback(&MagisterGnuplotAggregator::Write2d, plotAggregator));
386 
387  // Setup collectors.
388  m_terminalCollectors.SetType("ns3::ScalarCollector");
389  m_terminalCollectors.SetAttribute("InputDataType",
390  EnumValue(ScalarCollector::INPUT_DATA_TYPE_DOUBLE));
391  m_terminalCollectors.SetAttribute(
392  "OutputType",
393  EnumValue(ScalarCollector::OUTPUT_TYPE_AVERAGE_PER_SAMPLE));
395  Callback<void, double> callback =
396  MakeCallback(&DistributionCollector::TraceSinkDouble1, m_averagingCollector);
397  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
398  it != m_terminalCollectors.End();
399  ++it)
400  {
401  it->second->TraceConnectWithoutContext("Output", callback);
402  }
403  }
404  else
405  {
406  // Setup aggregator.
407  m_aggregator = CreateAggregator("ns3::MagisterGnuplotAggregator",
408  "OutputPath",
409  StringValue(GetOutputPath()),
410  "OutputFileName",
411  StringValue(GetName()));
412  Ptr<MagisterGnuplotAggregator> plotAggregator =
413  m_aggregator->GetObject<MagisterGnuplotAggregator>();
414  NS_ASSERT(plotAggregator != nullptr);
415  // plot->SetTitle ("");
416  plotAggregator->SetLegend("Antenna gain (in dB)", "Frequency");
417  plotAggregator->Set2dDatasetDefaultStyle(Gnuplot2dDataset::LINES);
418 
419  // Setup collectors.
420  m_terminalCollectors.SetType("ns3::DistributionCollector");
421  DistributionCollector::OutputType_t outputType =
422  DistributionCollector::OUTPUT_TYPE_HISTOGRAM;
424  {
425  outputType = DistributionCollector::OUTPUT_TYPE_PROBABILITY;
426  }
428  {
429  outputType = DistributionCollector::OUTPUT_TYPE_CUMULATIVE;
430  }
431  m_terminalCollectors.SetAttribute("OutputType", EnumValue(outputType));
433  for (CollectorMap::Iterator it = m_terminalCollectors.Begin();
434  it != m_terminalCollectors.End();
435  ++it)
436  {
437  const std::string context = it->second->GetName();
438  plotAggregator->Add2dDataset(context, context);
439  }
440  m_terminalCollectors.ConnectToAggregator("Output",
441  m_aggregator,
442  &MagisterGnuplotAggregator::Write2d);
443  }
444 
445  break;
446  }
447 
448  default:
449  NS_FATAL_ERROR("SatStatsDelayHelper - Invalid output type");
450  break;
451  }
452 
453  // Setup probes and connect them to the collectors.
454  InstallProbes();
455 }
456 
457 void
459 {
460  NS_LOG_FUNCTION(this);
461 
462  Callback<void, std::string, double> callback =
464 
465  NodeContainer utUsers = Singleton<SatTopology>::Get()->GetUtNodes();
466  for (NodeContainer::Iterator it = utUsers.Begin(); it != utUsers.End(); ++it)
467  {
468  Ptr<SatHandoverModule> hoModule = (*it)->GetObject<SatHandoverModule>();
469  if (!hoModule)
470  {
471  NS_LOG_INFO("UT " << *it << " does not check for antenna gain, bailing out.");
472  }
473  else
474  {
475  std::ostringstream oss;
476  oss << GetIdentifierForUt(*it);
477 
478  if (hoModule->TraceConnect("AntennaGainTrace", oss.str(), callback))
479  {
480  NS_LOG_INFO(this << " successfully connected with UT " << *it);
481  }
482  else
483  {
484  NS_LOG_WARN(this << " unable to connect to UT " << *it);
485  }
486  }
487  }
488 }
489 
490 } // 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.
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.