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 
31 NS_LOG_COMPONENT_DEFINE("SatPerPacketInterference");
32 
33 namespace ns3
34 {
35 
36 NS_OBJECT_ENSURE_REGISTERED(SatPerPacketInterference);
37 
38 TypeId
40 {
41  static TypeId tid = TypeId("ns3::SatPerPacketInterference")
42  .SetParent<SatInterference>()
43  .AddConstructor<SatPerPacketInterference>();
44 
45  return tid;
46 }
47 
48 TypeId
50 {
51  NS_LOG_FUNCTION(this);
52 
53  return GetTypeId();
54 }
55 
57  : m_residualPowerW(0.0),
58  m_rxing(false),
59  m_nextEventId(0),
60  m_enableTraceOutput(false),
61  m_channelType(),
62  m_rxBandwidth_Hz()
63 {
64  NS_LOG_FUNCTION(this);
65 }
66 
68  double rxBandwidthHz)
69  : m_residualPowerW(0.0),
70  m_rxing(false),
71  m_nextEventId(0),
72  m_enableTraceOutput(true),
73  m_channelType(channelType),
74  m_rxBandwidth_Hz(rxBandwidthHz)
75 {
76  NS_LOG_FUNCTION(this << channelType << rxBandwidthHz);
77 
78  if (m_rxBandwidth_Hz <= std::numeric_limits<double>::epsilon())
79  {
80  NS_FATAL_ERROR("SatPerPacketInterference::SatPerPacketInterference - Invalid value");
81  }
82 }
83 
85 {
86  NS_LOG_FUNCTION(this);
87 
88  Reset();
89 }
90 
91 Ptr<SatInterference::InterferenceChangeEvent>
92 SatPerPacketInterference::DoAdd(Time duration, double power, Address rxAddress)
93 {
94  NS_LOG_FUNCTION(this << duration << power << rxAddress);
95 
96  Ptr<SatInterference::InterferenceChangeEvent> event;
97  event = Create<SatInterference::InterferenceChangeEvent>(m_nextEventId++,
98  duration,
99  power,
100  rxAddress);
101  Time now = event->GetStartTime();
102 
103  NS_LOG_INFO("Add change: Duration= " << duration << ", Power= " << power << ", Time: " << now);
104 
105  // do update and clean-ups, if we are not receiving
106  if (!m_rxing)
107  {
108  InterferenceChanges::iterator nowIterator = m_interferenceChanges.upper_bound(now);
109 
110  for (InterferenceChanges::iterator i = m_interferenceChanges.begin(); i != nowIterator; i++)
111  {
112  uint32_t eventID;
113  long double powerValue;
114  std::tie(eventID, powerValue, std::ignore) = i->second;
115 
116  NS_LOG_INFO("Change to erase: Time= " << i->first << ", Id= " << eventID
117  << ", PowerValue= " << powerValue);
118 
119  m_residualPowerW += powerValue;
120 
121  NS_LOG_INFO("First power after erase: " << m_residualPowerW);
122  }
123  m_interferenceChanges.erase(m_interferenceChanges.begin(), nowIterator);
124  }
125 
126  NS_LOG_INFO("Change count before addition: " << m_interferenceChanges.size());
127 
128  // if no changes in future, first power should be zero
129  if (m_interferenceChanges.size() == 0)
130  {
131  if ((m_residualPowerW != 0) &&
132  std::fabs(m_residualPowerW) < std::numeric_limits<long double>::epsilon())
133  {
134  // if we end up here,
135  // reset first power (this probably due to roundin problem with very small values)
136  m_residualPowerW = 0;
137  }
138  }
139 
140  m_interferenceChanges.insert(
141  std::make_pair(now, InterferenceChange(event->GetId(), power, false)));
142  m_interferenceChanges.insert(
143  std::make_pair(event->GetEndTime(), InterferenceChange(event->GetId(), -power, true)));
144 
145  NS_LOG_INFO("Change count after addition: " << m_interferenceChanges.size());
146 
147  if (m_residualPowerW < 0)
148  {
149  // First power should never leak negative
150  NS_FATAL_ERROR("First power negative!!!");
151  }
152 
153  return event;
154 }
155 
156 std::vector<std::pair<double, double>>
157 SatPerPacketInterference::DoCalculate(Ptr<SatInterference::InterferenceChangeEvent> event)
158 {
159  NS_LOG_FUNCTION(this);
160 
161  if (m_rxing == false)
162  {
163  NS_FATAL_ERROR("Receiving is not set on!!!");
164  }
165 
166  double ifPowerW = m_residualPowerW;
167  double rxDuration = event->GetDuration().GetDouble();
168  double rxEndTime = event->GetEndTime().GetDouble();
169  bool ownStartReached = false;
170 
171  NS_LOG_INFO("Calculate: IfPower (W)= " << ifPowerW << ", Event ID= " << event->GetId()
172  << ", Duration= " << event->GetDuration()
173  << ", StartTime= " << event->GetStartTime()
174  << ", EndTime= " << event->GetEndTime());
175 
176  InterferenceChanges::iterator currentItem = m_interferenceChanges.begin();
177 
178  // calculate power values until own "stop" event found (own negative power event)
179  while (currentItem != m_interferenceChanges.end())
180  {
181  uint32_t eventID;
182  long double powerValue;
183  bool isEndEvent;
184  std::tie(eventID, powerValue, isEndEvent) = currentItem->second;
185 
186  if (event->GetId() == eventID)
187  {
188  if (isEndEvent)
189  {
190  NS_LOG_INFO("IfPower after end event: " << ifPowerW);
191  break;
192  }
193  // stop increasing power value fully, when own 'start' event is reached
194  // needed to support multiple simultaneous receiving (currently not supported)
195  // own event is not updated to ifPower
196  ownStartReached = true;
197  onOwnStartReached(ifPowerW);
198  }
199  else if (ownStartReached)
200  {
201  // increase/decrease interference power with relative part of duration of power change
202  // in list
203  double itemTime = currentItem->first.GetDouble();
204  onInterferentEvent(((rxEndTime - itemTime) / rxDuration), powerValue, ifPowerW);
205 
206  NS_LOG_INFO("Update (partial): ID: " << eventID << ", Power (W)= " << powerValue
207  << ", Time= " << currentItem->first
208  << ", DeltaTime= " << (rxEndTime - itemTime));
209 
210  NS_LOG_INFO("IfPower after update: " << ifPowerW);
211  }
212  else
213  {
214  // increase/decrease interference power with full power change in list
215  ifPowerW += powerValue;
216 
217  NS_LOG_INFO("Update (full): ID: " << eventID << ", Power (W)= " << powerValue);
218  NS_LOG_INFO("IfPower after update: " << ifPowerW);
219  }
220 
221  currentItem++;
222  }
223 
225  {
226  std::vector<double> tempVector;
227  tempVector.push_back(Now().GetSeconds());
228  tempVector.push_back(ifPowerW / m_rxBandwidth_Hz);
229  Singleton<SatInterferenceOutputTraceContainer>::Get()->AddToContainer(
230  std::make_pair(event->GetSatEarthStationAddress(), m_channelType),
231  tempVector);
232  }
233 
234  std::vector<std::pair<double, double>> ifPowerPerFragment;
235  ifPowerPerFragment.emplace_back(1.0, ifPowerW);
236 
237  return ifPowerPerFragment;
238 }
239 
240 void
242 {
243  // do nothing, meant for subclasses to override
244 }
245 
246 void
248  double interferenceValue,
249  double& ifPowerW)
250 {
251  ifPowerW += timeRatio * interferenceValue;
252 }
253 
254 void
256 {
257  NS_LOG_FUNCTION(this);
258 
259  m_interferenceChanges.clear();
260  m_rxing = false;
261  m_residualPowerW = 0.0;
262 }
263 
264 void
265 SatPerPacketInterference::DoNotifyRxStart(Ptr<SatInterference::InterferenceChangeEvent> event)
266 {
267  NS_LOG_FUNCTION(this);
268 
269  std::pair<std::set<uint32_t>::iterator, bool> result = m_rxEventIds.insert(event->GetId());
270 
271  NS_ASSERT(result.second);
272  m_rxing = true;
273 }
274 
275 void
276 SatPerPacketInterference::DoNotifyRxEnd(Ptr<SatInterference::InterferenceChangeEvent> event)
277 {
278  NS_LOG_FUNCTION(this);
279 
280  m_rxEventIds.erase(event->GetId());
281 
282  if (m_rxEventIds.empty())
283  {
284  m_rxing = false;
285  }
286 }
287 
288 void
290 {
291  NS_LOG_FUNCTION(this);
292 
293  SatInterference::DoDispose();
294 }
295 
296 void
298 {
299  NS_LOG_FUNCTION(this << rxBandwidth);
300 
301  if (rxBandwidth <= std::numeric_limits<double>::epsilon())
302  {
303  NS_FATAL_ERROR("SatPerPacketInterference::SetRxBandwidth - Invalid value");
304  }
305 
306  m_rxBandwidth_Hz = rxBandwidth;
307 }
308 
309 } // namespace ns3
310 
311 // 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.