satellite-per-packet-interference.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  * Copyright (c) 2018 CNES
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Jani Puttonen <jani.puttonen@magister.fi>
20  * Author: Mathias Ettinger <mettinger@toulouse.viveris.fr>
21  */
22 
24 
25 #include <ns3/log.h>
26 #include <ns3/simulator.h>
27 #include <ns3/singleton.h>
28 
29 #include <algorithm>
30 #include <cmath>
31 #include <istream>
32 #include <limits>
33 #include <set>
34 #include <tuple>
35 #include <utility>
36 #include <vector>
37 
38 NS_LOG_COMPONENT_DEFINE("SatPerPacketInterference");
39 
40 namespace ns3
41 {
42 
43 NS_OBJECT_ENSURE_REGISTERED(SatPerPacketInterference);
44 
45 TypeId
47 {
48  static TypeId tid = TypeId("ns3::SatPerPacketInterference")
49  .SetParent<SatInterference>()
50  .AddConstructor<SatPerPacketInterference>();
51 
52  return tid;
53 }
54 
55 TypeId
57 {
58  NS_LOG_FUNCTION(this);
59 
60  return GetTypeId();
61 }
62 
64  : m_residualPowerW(0.0),
65  m_rxing(false),
66  m_nextEventId(0),
67  m_enableTraceOutput(false),
68  m_channelType(),
69  m_rxBandwidth_Hz()
70 {
71  NS_LOG_FUNCTION(this);
72 }
73 
75  double rxBandwidthHz)
76  : m_residualPowerW(0.0),
77  m_rxing(false),
78  m_nextEventId(0),
79  m_enableTraceOutput(true),
80  m_channelType(channelType),
81  m_rxBandwidth_Hz(rxBandwidthHz)
82 {
83  NS_LOG_FUNCTION(this << channelType << rxBandwidthHz);
84 
85  if (m_rxBandwidth_Hz <= std::numeric_limits<double>::epsilon())
86  {
87  NS_FATAL_ERROR("SatPerPacketInterference::SatPerPacketInterference - Invalid value");
88  }
89 }
90 
92 {
93  NS_LOG_FUNCTION(this);
94 
95  Reset();
96 }
97 
98 Ptr<SatInterference::InterferenceChangeEvent>
99 SatPerPacketInterference::DoAdd(Time duration, double power, Address rxAddress)
100 {
101  NS_LOG_FUNCTION(this << duration << power << rxAddress);
102 
103  Ptr<SatInterference::InterferenceChangeEvent> event;
104  event = Create<SatInterference::InterferenceChangeEvent>(m_nextEventId++,
105  duration,
106  power,
107  rxAddress);
108  Time now = event->GetStartTime();
109 
110  NS_LOG_INFO("Add change: Duration= " << duration << ", Power= " << power << ", Time: " << now);
111 
112  // do update and clean-ups, if we are not receiving
113  if (!m_rxing)
114  {
115  InterferenceChanges::iterator nowIterator = m_interferenceChanges.upper_bound(now);
116 
117  for (InterferenceChanges::iterator i = m_interferenceChanges.begin(); i != nowIterator; i++)
118  {
119  uint32_t eventID;
120  long double powerValue;
121  std::tie(eventID, powerValue, std::ignore) = i->second;
122 
123  NS_LOG_INFO("Change to erase: Time= " << i->first << ", Id= " << eventID
124  << ", PowerValue= " << powerValue);
125 
126  m_residualPowerW += powerValue;
127 
128  NS_LOG_INFO("First power after erase: " << m_residualPowerW);
129  }
130  m_interferenceChanges.erase(m_interferenceChanges.begin(), nowIterator);
131  }
132 
133  NS_LOG_INFO("Change count before addition: " << m_interferenceChanges.size());
134 
135  // if no changes in future, first power should be zero
136  if (m_interferenceChanges.size() == 0)
137  {
138  if ((m_residualPowerW != 0) &&
139  std::fabs(m_residualPowerW) < std::numeric_limits<long double>::epsilon())
140  {
141  // if we end up here,
142  // reset first power (this probably due to roundin problem with very small values)
143  m_residualPowerW = 0;
144  }
145  }
146 
147  m_interferenceChanges.insert(
148  std::make_pair(now, InterferenceChange(event->GetId(), power, false)));
149  m_interferenceChanges.insert(
150  std::make_pair(event->GetEndTime(), InterferenceChange(event->GetId(), -power, true)));
151 
152  NS_LOG_INFO("Change count after addition: " << m_interferenceChanges.size());
153 
154  if (m_residualPowerW < 0)
155  {
156  // First power should never leak negative
157  NS_FATAL_ERROR("First power negative!!!");
158  }
159 
160  return event;
161 }
162 
163 std::vector<std::pair<double, double>>
164 SatPerPacketInterference::DoCalculate(Ptr<SatInterference::InterferenceChangeEvent> event)
165 {
166  NS_LOG_FUNCTION(this);
167 
168  if (m_rxing == false)
169  {
170  NS_FATAL_ERROR("Receiving is not set on!!!");
171  }
172 
173  double ifPowerW = m_residualPowerW;
174  double rxDuration = event->GetDuration().GetDouble();
175  double rxEndTime = event->GetEndTime().GetDouble();
176  bool ownStartReached = false;
177 
178  NS_LOG_INFO("Calculate: IfPower (W)= " << ifPowerW << ", Event ID= " << event->GetId()
179  << ", Duration= " << event->GetDuration()
180  << ", StartTime= " << event->GetStartTime()
181  << ", EndTime= " << event->GetEndTime());
182 
183  InterferenceChanges::iterator currentItem = m_interferenceChanges.begin();
184 
185  // calculate power values until own "stop" event found (own negative power event)
186  while (currentItem != m_interferenceChanges.end())
187  {
188  uint32_t eventID;
189  long double powerValue;
190  bool isEndEvent;
191  std::tie(eventID, powerValue, isEndEvent) = currentItem->second;
192 
193  if (event->GetId() == eventID)
194  {
195  if (isEndEvent)
196  {
197  NS_LOG_INFO("IfPower after end event: " << ifPowerW);
198  break;
199  }
200  // stop increasing power value fully, when own 'start' event is reached
201  // needed to support multiple simultaneous receiving (currently not supported)
202  // own event is not updated to ifPower
203  ownStartReached = true;
204  onOwnStartReached(ifPowerW);
205  }
206  else if (ownStartReached)
207  {
208  // increase/decrease interference power with relative part of duration of power change
209  // in list
210  double itemTime = currentItem->first.GetDouble();
211  onInterferentEvent(((rxEndTime - itemTime) / rxDuration), powerValue, ifPowerW);
212 
213  NS_LOG_INFO("Update (partial): ID: " << eventID << ", Power (W)= " << powerValue
214  << ", Time= " << currentItem->first
215  << ", DeltaTime= " << (rxEndTime - itemTime));
216 
217  NS_LOG_INFO("IfPower after update: " << ifPowerW);
218  }
219  else
220  {
221  // increase/decrease interference power with full power change in list
222  ifPowerW += powerValue;
223 
224  NS_LOG_INFO("Update (full): ID: " << eventID << ", Power (W)= " << powerValue);
225  NS_LOG_INFO("IfPower after update: " << ifPowerW);
226  }
227 
228  currentItem++;
229  }
230 
232  {
233  std::vector<double> tempVector;
234  tempVector.push_back(Now().GetSeconds());
235  tempVector.push_back(ifPowerW / m_rxBandwidth_Hz);
236  Singleton<SatInterferenceOutputTraceContainer>::Get()->AddToContainer(
237  std::make_pair(event->GetSatEarthStationAddress(), m_channelType),
238  tempVector);
239  }
240 
241  std::vector<std::pair<double, double>> ifPowerPerFragment;
242  ifPowerPerFragment.emplace_back(1.0, ifPowerW);
243 
244  return ifPowerPerFragment;
245 }
246 
247 void
249 {
250  // do nothing, meant for subclasses to override
251 }
252 
253 void
255  double interferenceValue,
256  double& ifPowerW)
257 {
258  ifPowerW += timeRatio * interferenceValue;
259 }
260 
261 void
263 {
264  NS_LOG_FUNCTION(this);
265 
266  m_interferenceChanges.clear();
267  m_rxing = false;
268  m_residualPowerW = 0.0;
269 }
270 
271 void
272 SatPerPacketInterference::DoNotifyRxStart(Ptr<SatInterference::InterferenceChangeEvent> event)
273 {
274  NS_LOG_FUNCTION(this);
275 
276  std::pair<std::set<uint32_t>::iterator, bool> result = m_rxEventIds.insert(event->GetId());
277 
278  NS_ASSERT(result.second);
279  m_rxing = true;
280 }
281 
282 void
283 SatPerPacketInterference::DoNotifyRxEnd(Ptr<SatInterference::InterferenceChangeEvent> event)
284 {
285  NS_LOG_FUNCTION(this);
286 
287  m_rxEventIds.erase(event->GetId());
288 
289  if (m_rxEventIds.empty())
290  {
291  m_rxing = false;
292  }
293 }
294 
295 void
297 {
298  NS_LOG_FUNCTION(this);
299 
300  SatInterference::DoDispose();
301 }
302 
303 void
305 {
306  NS_LOG_FUNCTION(this << rxBandwidth);
307 
308  if (rxBandwidth <= std::numeric_limits<double>::epsilon())
309  {
310  NS_FATAL_ERROR("SatPerPacketInterference::SetRxBandwidth - Invalid value");
311  }
312 
313  m_rxBandwidth_Hz = rxBandwidth;
314 }
315 
316 } // namespace ns3
317 
318 // namespace ns3
ChannelType_t
Types of channel.
Abstract class defining interface for interference calculations objects.
void Reset(void)
Resets current interference.
virtual void DoReset(void)
Resets current interference.
bool m_rxing
flag to indicate that at least one receiving is on
long double m_residualPowerW
Residual power value for interference.
virtual void DoNotifyRxEnd(Ptr< SatInterference::InterferenceChangeEvent > event)
Notifies that RX is ended by a receiver.
InterferenceChanges m_interferenceChanges
interference change list
virtual void DoNotifyRxStart(Ptr< SatInterference::InterferenceChangeEvent > event)
Notifies that RX is started by a receiver.
std::set< uint32_t > m_rxEventIds
notified interference event IDs
virtual void onInterferentEvent(long double timeRatio, double interferenceValue, double &ifPowerW)
Helper function meant for subclasses to override.
std::tuple< uint32_t, long double, bool > InterferenceChange
virtual std::vector< std::pair< double, double > > DoCalculate(Ptr< SatInterference::InterferenceChangeEvent > event)
Calculates interference power for the given reference Sets final power at end time to finalPower.
virtual void onOwnStartReached(double ifPowerW)
Helper function meant for subclasses to override.
virtual Ptr< SatInterference::InterferenceChangeEvent > DoAdd(Time rxDuration, double rxPower, Address rxAddress)
Adds interference power to interference object.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.