satellite-input-fstream-time-long-double-container.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: Frans Laakso <frans.laakso@magister.fi>
19  */
20 
22 
23 #include "ns3/abort.h"
24 #include "ns3/log.h"
25 #include "ns3/simulator.h"
26 
27 NS_LOG_COMPONENT_DEFINE("SatInputFileStreamTimeLongDoubleContainer");
28 
29 namespace ns3
30 {
31 
32 TypeId
34 {
35  static TypeId tid = TypeId("ns3::SatInputFileStreamTimeLongDoubleContainer")
36  .SetParent<Object>()
37  .AddConstructor<SatInputFileStreamTimeLongDoubleContainer>();
38  return tid;
39 }
40 
42  std::string filename,
43  std::ios::openmode filemode,
44  uint32_t valuesInRow)
45  : m_inputFileStreamWrapper(),
46  m_inputFileStream(),
47  m_container(),
48  m_fileName(filename),
49  m_fileMode(filemode),
50  m_valuesInRow(valuesInRow),
51  m_lastValidPosition(0),
52  m_numOfPasses(0),
53  m_timeShiftValue(0),
54  m_timeColumn(0)
55 {
56  NS_LOG_FUNCTION(this << m_fileName << m_fileMode);
57 
59 }
60 
62  : m_inputFileStreamWrapper(),
63  m_inputFileStream(),
64  m_container(),
65  m_fileName(),
66  m_fileMode(),
67  m_valuesInRow(),
68  m_lastValidPosition(),
69  m_numOfPasses(),
70  m_timeShiftValue(),
71  m_timeColumn()
72 {
73  NS_LOG_FUNCTION(this);
74  NS_FATAL_ERROR("SatInputFileStreamTimeLongDoubleContainer::"
75  "SatInputFileStreamTimeLongDoubleContainer - Constructor not in use");
76 }
77 
79 {
80  NS_LOG_FUNCTION(this);
81 
82  Reset();
83 }
84 
85 void
87 {
88  NS_LOG_FUNCTION(this);
89 
90  Reset();
91  Object::DoDispose();
92 }
93 
94 void
96  std::ios::openmode filemode,
97  uint32_t valuesInRow)
98 {
99  NS_LOG_FUNCTION(this);
100 
101  ClearContainer();
102 
103  m_fileName = filename;
104  m_fileMode = filemode;
105  m_valuesInRow = valuesInRow;
106 
107  m_inputFileStreamWrapper = new SatInputFileStreamWrapper(filename, filemode);
109 
110  if (m_inputFileStream->is_open())
111  {
112  std::vector<long double> tempVector = ReadRow();
113 
114  while (!m_inputFileStream->eof())
115  {
116  m_container.push_back(tempVector);
117  tempVector = ReadRow();
118  }
119  m_inputFileStream->close();
120  }
121  else
122  {
123  NS_ABORT_MSG("Input stream is not valid for reading.");
124  }
125 
127 
128  ResetStream();
129 }
130 
131 std::vector<long double>
133 {
134  NS_LOG_FUNCTION(this);
135 
136  long double tempValue;
137  std::vector<long double> tempVector;
138 
139  for (uint32_t i = 0; i < m_valuesInRow; i++)
140  {
141  *m_inputFileStream >> tempValue;
142  tempVector.push_back(tempValue);
143  }
144  return tempVector;
145 }
146 
147 void
149 {
150  NS_LOG_FUNCTION(this);
151 
153  if (m_container.size() < 1)
154  {
155  NS_FATAL_ERROR("SatInputFileStreamTimeLongDoubleContainer::UpdateContainer - Empty file");
156  }
157  else if (m_container.size() == 1)
158  {
159  if (m_container[m_container.size() - 1].at(m_timeColumn) == 0)
160  {
161  NS_FATAL_ERROR("SatInputFileStreamTimeLongDoubleContainer::UpdateContainer - Invalid "
162  "input file format (time sample error)");
163  }
164  }
165  else
166  {
167  double tempValue1 = m_container[0].at(m_timeColumn);
168 
169  for (uint32_t i = 1; i < m_container.size(); i++)
170  {
171  if (tempValue1 > m_container[i].at(m_timeColumn))
172  {
173  NS_FATAL_ERROR("SatInputFileStreamTimeLongDoubleContainer::UpdateContainer - "
174  "Invalid input file format (time sample error)");
175  }
176  tempValue1 = m_container[i].at(m_timeColumn);
177  }
178  }
179 }
180 
181 std::vector<long double>
183 {
184  NS_LOG_FUNCTION(this);
185 
186  while (!FindNextClosest(m_lastValidPosition, m_timeShiftValue, Now().GetSeconds()))
187  {
189  m_numOfPasses++;
191 
192  NS_LOG_INFO("Looping samples again with shift value: " << m_timeShiftValue);
193  }
194 
195  if (m_numOfPasses > 0)
196  {
197  std::cout
198  << "WARNING! - "
199  "SatInputFileStreamTimeLongDoubleContainer::ProceedToNextClosestTimeSample for "
200  << m_fileName << " is out of samples @ time sample " << Now().GetSeconds()
201  << " (passes " << m_numOfPasses << ")" << std::endl;
202  std::cout << "The container will loop samples from the beginning." << std::endl;
203  }
204 
206 }
207 
208 std::vector<long double>
210 {
211  NS_LOG_FUNCTION(this);
212 
213  long double currentTime = Now().GetSeconds();
215 
216  std::vector<long double> selectedPosition = m_container[m_lastValidPosition];
217  long double selectedTime = selectedPosition.at(m_timeColumn);
218 
219  // Easy case: a time sample for the current time exist
220  if (selectedTime == currentTime)
221  {
222  return selectedPosition;
223  }
224 
225  // Fetch the second position to perform linear interpolation
226  std::vector<long double> closestPosition;
227  if (selectedTime > currentTime)
228  {
229  if (m_lastValidPosition == 0)
230  {
231  // No previous position available, abort
232  return selectedPosition;
233  }
234  closestPosition = m_container[m_lastValidPosition - 1];
235  }
236  else
237  {
238  if (m_lastValidPosition == m_container.size() - 1)
239  {
240  // No next position available, abort
241  return selectedPosition;
242  }
243  closestPosition = m_container[m_lastValidPosition + 1];
244  }
245 
246  long double linearCoefficient =
247  (currentTime - selectedTime) / (closestPosition.at(m_timeColumn) - selectedTime);
248  std::size_t rowSize = selectedPosition.size();
249  std::vector<long double> interpolatedPosition(rowSize);
250  for (std::size_t i = 0; i < rowSize; ++i)
251  {
252  interpolatedPosition[i] =
253  selectedPosition[i] + linearCoefficient * (closestPosition[i] - selectedPosition[i]);
254  }
255 
256  return interpolatedPosition;
257 }
258 
259 bool
261  long double timeShiftValue,
262  long double comparisonTimeValue)
263 {
264  NS_LOG_FUNCTION(this);
265 
266  NS_ASSERT(m_timeColumn < m_valuesInRow);
267  NS_ASSERT(m_container.size() > 0);
268  NS_ASSERT(lastValidPosition >= 0 && lastValidPosition < m_container.size());
269 
270  NS_LOG_INFO("LastValidPosition " << lastValidPosition << " column " << m_timeColumn
271  << " timeShiftValue " << timeShiftValue
272  << " comparisonTimeValue " << comparisonTimeValue);
273 
274  bool valueFound = false;
275 
276  for (uint32_t i = lastValidPosition; i < m_container.size(); i++)
277  {
278  if (m_container[i].at(m_timeColumn) + timeShiftValue >= comparisonTimeValue)
279  {
280  long double difference1 = std::abs(m_container[lastValidPosition].at(m_timeColumn) +
281  timeShiftValue - comparisonTimeValue);
282  long double difference2 =
283  std::abs(m_container[i].at(m_timeColumn) + timeShiftValue - comparisonTimeValue);
284 
285  if (difference1 < difference2)
286  {
287  m_lastValidPosition = lastValidPosition;
288  }
289  else
290  {
292  }
293  valueFound = true;
294  break;
295  }
296  lastValidPosition = i;
297  }
298 
299  if (valueFound && m_numOfPasses > 0 && m_lastValidPosition == 0)
300  {
301  long double difference1 = std::abs(m_container[m_lastValidPosition].at(m_timeColumn) +
302  timeShiftValue - comparisonTimeValue);
303  long double difference2 =
304  std::abs(m_container[m_container.size() - 1].at(m_timeColumn) +
305  ((m_numOfPasses - 1) * m_container[m_container.size() - 1].at(m_timeColumn)) -
306  comparisonTimeValue);
307 
308  if (difference1 > difference2)
309  {
310  m_lastValidPosition = m_container.size() - 1;
311  m_numOfPasses--;
313  }
314  }
315 
316  NS_LOG_INFO("Done: " << valueFound
317  << " value: " << m_container[m_lastValidPosition].at(m_timeColumn)
318  << " @ line: " << m_lastValidPosition + 1 << " comparison time value: "
319  << comparisonTimeValue << " passes: " << m_numOfPasses);
320 
321  return valueFound;
322 }
323 
324 void
326 {
327  NS_LOG_FUNCTION(this);
328 
329  ResetStream();
330  ClearContainer();
331 }
332 
333 void
335 {
336  NS_LOG_FUNCTION(this);
337 
338  if (m_inputFileStreamWrapper != NULL)
339  {
342  }
343  m_inputFileStream = 0;
344 }
345 
346 void
348 {
349  NS_LOG_FUNCTION(this);
350 
351  if (!m_container.empty())
352  {
353  for (uint32_t i = 0; i < m_container.size(); i++)
354  {
355  if (!m_container[i].empty())
356  {
357  m_container[i].clear();
358  }
359  }
360  m_container.clear();
361  }
362 
363  m_valuesInRow = 0;
365  m_numOfPasses = 0;
366  m_timeShiftValue = 0;
367 }
368 
369 } // namespace ns3
std::vector< long double > ReadRow()
Function for reading a row from file.
uint32_t m_timeColumn
Index for column which contains time information.
bool FindNextClosest(uint32_t lastValidPosition, long double timeShiftValue, double long comparisonTimeValue)
Function for locating the next closest value index.
void UpdateContainer(std::string filename, std::ios::openmode filemode, uint32_t valuesInRow)
Function for updating the container.
std::vector< long double > ProceedToNextClosestTimeSample()
Function for locating the next closest time sample and returning the values related to it.
uint32_t m_numOfPasses
Number for how many times the available samples have been looped over.
std::vector< long double > InterpolateBetweenClosestTimeSamples()
Function for locating time samples enclosing the current time and a linear interpolation between thes...
std::vector< std::vector< long double > > m_container
Container for value rows.
SatInputFileStreamWrapper * m_inputFileStreamWrapper
Pointer to input file stream wrapper.
A class encapsulating an STL input stream.
std::ifstream * GetStream(void)
Return a pointer to an ifstream previously set in the wrapper.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.