satellite-mobility-observer.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 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: Sami Rantanen <sami.rantanen@magister.fi>
19  */
20 
22 
23 #include "satellite-utils.h"
24 
25 #include <ns3/boolean.h>
26 #include <ns3/double.h>
27 #include <ns3/log.h>
28 #include <ns3/pointer.h>
29 #include <ns3/trace-source-accessor.h>
30 
31 #include <cmath>
32 #include <stdint.h>
33 #include <string>
34 
35 NS_LOG_COMPONENT_DEFINE("SatMobilityObserver");
36 
37 namespace ns3
38 {
39 
40 NS_OBJECT_ENSURE_REGISTERED(SatMobilityObserver);
41 
42 TypeId
44 {
45  static TypeId tid =
46  TypeId("ns3::SatMobilityObserver")
47  .SetParent<Object>()
48  .AddAttribute("OwnMobility",
49  "Own mobility.",
50  PointerValue(),
51  MakePointerAccessor(&SatMobilityObserver::m_ownMobility),
52  MakePointerChecker<SatMobilityModel>())
53  .AddAttribute("SatelliteMobility",
54  "The mobility of the satellite.",
55  PointerValue(),
56  MakePointerAccessor(&SatMobilityObserver::m_geoSatMobility),
57  MakePointerChecker<SatMobilityModel>())
58  .AddAttribute("AnotherMobility",
59  "The mobility of the another end node.",
60  PointerValue(),
61  MakePointerAccessor(&SatMobilityObserver::m_anotherMobility),
62  MakePointerChecker<SatMobilityModel>())
63  .AddAttribute("OwnPropagation",
64  "Own propagation delay model.",
65  PointerValue(),
66  MakePointerAccessor(&SatMobilityObserver::m_ownProgDelayModel),
67  MakePointerChecker<SatMobilityModel>())
68  .AddAttribute("AnotherPropagation",
69  "The propagation delay model of the another end node.",
70  PointerValue(),
72  MakePointerChecker<SatMobilityModel>())
73  .AddAttribute("MinAltitude",
74  "The minimum altitude accepted for own position.",
75  DoubleValue(0),
76  MakeDoubleAccessor(&SatMobilityObserver::m_minAltitude),
77  MakeDoubleChecker<double>())
78  .AddAttribute("MaxAltitude",
79  "The maximum altitude accepted for own position.",
80  DoubleValue(500.00),
81  MakeDoubleAccessor(&SatMobilityObserver::m_maxAltitude),
82  MakeDoubleChecker<double>())
83  .AddTraceSource("PropertyChanged",
84  "The value of the some property has changed",
85  MakeTraceSourceAccessor(&SatMobilityObserver::m_propertyChangeTrace),
86  "ns3::SatMobilityObserver::PropertyChangedCallback");
87  return tid;
88 }
89 
90 TypeId
92 {
93  NS_LOG_FUNCTION(this);
94 
95  return GetTypeId();
96 }
97 
99 {
100  NS_LOG_FUNCTION(this);
101 
102  // this constructor version should not be used
103  NS_ASSERT(false);
104 }
105 
106 SatMobilityObserver::SatMobilityObserver(Ptr<SatMobilityModel> ownMobility,
107  Ptr<SatMobilityModel> geoSatMobility,
108  bool isRegenerative)
109  : m_ownMobility(ownMobility),
110  m_anotherMobility(nullptr),
111  m_geoSatMobility(geoSatMobility),
112  m_ownProgDelayModel(nullptr),
113  m_anotherProgDelayModel(nullptr),
114  m_initialized(false),
115  m_isRegenerative(isRegenerative)
116 {
117  NS_LOG_FUNCTION(this << ownMobility << geoSatMobility);
118 
119  GeoCoordinate satellitePosition = m_geoSatMobility->GetGeoPosition();
120  GeoCoordinate ownPosition = m_ownMobility->GetGeoPosition();
121 
122  // same reference ellipsoide must be used by mobilities
123  NS_ASSERT(satellitePosition.GetRefEllipsoid() == ownPosition.GetRefEllipsoid());
124 
125  double satelliteAltitude = satellitePosition.GetAltitude();
126 
127  // satellite is expected to be in the sky
128  NS_ASSERT(satelliteAltitude > 0.0);
129 
130  // calculate radius of the earth using satellite information
131  m_earthRadius =
132  CalculateDistance(satellitePosition.ToVector(), Vector(0, 0, 0)) - satelliteAltitude;
133 
135  m_updateElevationAngle = true;
136  m_updateTimingAdvance = true;
137  m_timingAdvance_s = Seconds(0);
138 
139  m_geoSatMobility->TraceConnect("SatCourseChange",
140  "Satellite",
141  MakeCallback(&SatMobilityObserver::PositionChanged, this));
142  m_ownMobility->TraceConnect("SatCourseChange",
143  "Own",
144  MakeCallback(&SatMobilityObserver::PositionChanged, this));
145 
146  m_velocity = 0.0;
147 
148  m_initialized = true;
149 }
150 
151 void
153 {
154  NS_LOG_FUNCTION(this);
155 
156  m_ownMobility = nullptr;
157  m_anotherMobility = nullptr;
158  m_geoSatMobility = nullptr;
159  m_ownProgDelayModel = nullptr;
160  m_anotherProgDelayModel = nullptr;
161 }
162 
164 {
165  NS_LOG_FUNCTION(this);
166 }
167 
168 void
169 SatMobilityObserver::ObserveTimingAdvance(Ptr<PropagationDelayModel> ownDelayModel,
170  Ptr<PropagationDelayModel> anotherDelayModel,
171  Ptr<SatMobilityModel> anotherMobility)
172 {
173  NS_LOG_FUNCTION(this << ownDelayModel << anotherDelayModel << anotherMobility);
174 
175  NS_ASSERT(ownDelayModel != nullptr);
176  NS_ASSERT(anotherDelayModel != nullptr);
177  NS_ASSERT(anotherMobility != nullptr);
178 
179  auto cb = MakeCallback(&SatMobilityObserver::PositionChanged, this);
180  if (m_anotherMobility != nullptr)
181  {
182  m_anotherMobility->TraceDisconnect("SatCourseChange", "Another", cb);
183  }
184 
185  m_ownProgDelayModel = ownDelayModel;
186  m_anotherProgDelayModel = anotherDelayModel;
187  m_anotherMobility = anotherMobility;
188 
189  // same reference ellipsoide must be used by mobilities
190  NS_ASSERT(m_anotherMobility->GetGeoPosition().GetRefEllipsoid() ==
191  m_ownMobility->GetGeoPosition().GetRefEllipsoid());
192 
193  m_anotherMobility->TraceConnect("SatCourseChange", "Another", cb);
194 }
195 
196 double
198 {
199  NS_LOG_FUNCTION(this);
200 
201  if (m_updateElevationAngle == true)
202  {
203  // same reference ellipsoide must be used by mobilities
204  NS_ASSERT(m_geoSatMobility->GetGeoPosition().GetRefEllipsoid() ==
205  m_ownMobility->GetGeoPosition().GetRefEllipsoid());
206 
208  m_updateElevationAngle = false;
209  }
210 
211  return m_elevationAngle;
212 }
213 
214 double
216 {
217  NS_LOG_FUNCTION(this);
218 
219  Vector velocity = m_ownMobility->GetVelocity();
220  m_velocity = std::sqrt((velocity.x * velocity.x) + (velocity.y * velocity.y) +
221  (velocity.z * velocity.z));
222 
223  return m_velocity;
224 }
225 
226 Time
228 {
229  NS_LOG_FUNCTION(this);
230 
231  // update timing advance, if another end is given and update needed
232  if ((m_anotherMobility != nullptr) && (m_updateTimingAdvance == true))
233  {
234  // another propagation delay is expected to be given
235  NS_ASSERT(m_anotherProgDelayModel != nullptr);
236 
237  // same reference ellipsoide must be used by mobilities
238  NS_ASSERT(m_geoSatMobility->GetGeoPosition().GetRefEllipsoid() ==
239  m_ownMobility->GetGeoPosition().GetRefEllipsoid());
240 
241  // same reference ellipsoide must be used by mobilities
242  NS_ASSERT(m_anotherMobility->GetGeoPosition().GetRefEllipsoid() ==
243  m_ownMobility->GetGeoPosition().GetRefEllipsoid());
244 
246  m_updateTimingAdvance = false;
247  }
248 
249  return m_timingAdvance_s;
250 }
251 
252 void
254 {
255  NS_LOG_FUNCTION(this);
256 
257  if (m_initialized)
258  {
259  m_propertyChangeTrace(this);
260  }
261 }
262 
263 void
264 SatMobilityObserver::PositionChanged(std::string context, Ptr<const SatMobilityModel> position)
265 {
266  NS_LOG_FUNCTION(this << context << position);
267 
268  // set flag on to idicate that elevation angle is needed to update,
269  // when its status is requested with method GetElevationAngle
270  m_updateElevationAngle = true;
271 
272  // set flag on to idicate that timing advance is needed to update,
273  // when its status is requested with method GetTimingAdvance
274  m_updateTimingAdvance = true;
275 
276  // call satellite statis updated routine to update needed variables
277  if (context == "Satellite")
278  {
280  }
281 
283 }
284 
285 void
287 {
288  NS_LOG_FUNCTION(this);
289 
290  m_elevationAngle = NAN;
291 
292  GeoCoordinate ownPosition = m_ownMobility->GetGeoPosition();
293  GeoCoordinate satellitePosition = m_geoSatMobility->GetGeoPosition();
294 
295  NS_ASSERT(ownPosition.GetAltitude() >= m_minAltitude &&
296  ownPosition.GetAltitude() <= m_maxAltitude);
297 
298  // elevation angle is always calculated at earth surface, so set altitude to zero
299  ownPosition.SetAltitude(0);
300 
301  // calculate distance from Earth location to satellite
302  double distanceToSatellite =
303  CalculateDistance(ownPosition.ToVector(), satellitePosition.ToVector());
304 
305  // calculate elevation angle only, if satellite can be seen from own position
306  if (distanceToSatellite <= m_maxDistanceToSatellite)
307  {
308  double earthLatitude = SatUtils::DegreesToRadians(ownPosition.GetLatitude());
309  double satLatitude = SatUtils::DegreesToRadians(satellitePosition.GetLatitude());
310 
311  double earthLongitude = SatUtils::DegreesToRadians(ownPosition.GetLongitude());
312  double satLongitude = SatUtils::DegreesToRadians(satellitePosition.GetLongitude());
313 
314  double longitudeDelta = satLongitude - earthLongitude;
315 
316  // Calculate cosini of the central angle
317  // TODO: Currently we have assumed that the reference ellipsoide is a sphere.
318  // This should be accurate enough for elevation angle calculation with also other
319  // reference ellipsoides. But, if more accurate calculation is needed, then the used
320  // reference ellipsoide is needed to be take into account.
321  double centralAngleCos =
322  (std::cos(earthLatitude) * std::cos(satLatitude) * std::cos(longitudeDelta)) +
323  (std::sin(earthLatitude) * std::sin(satLatitude));
324 
325  // Calculate cosini of the elavation angle
326  double elCos =
327  std::sin(std::acos(centralAngleCos)) /
328  std::sqrt(1 + std::pow(m_radiusRatio, 2) - 2 * m_radiusRatio * centralAngleCos);
329 
330  m_elevationAngle = SatUtils::RadiansToDegrees(std::acos(elCos));
331  }
332 }
333 
334 void
336 {
337  NS_LOG_FUNCTION(this);
338 
339  NS_ASSERT(m_ownProgDelayModel != nullptr);
340  NS_ASSERT(m_anotherProgDelayModel != nullptr);
341 
342  if (m_isRegenerative)
343  {
345  }
346  else
347  {
350  }
351 }
352 
353 void
355 {
356  NS_LOG_FUNCTION(this);
357 
358  double satelliteAltitude = m_geoSatMobility->GetGeoPosition().GetAltitude();
359 
360  // satellite is expected to be in the sky
361  NS_ASSERT(satelliteAltitude > 0.0);
362 
363  // calculate maximum distance where UT or GW can be on the Earth.
364  double satelliteRadius = satelliteAltitude + m_earthRadius;
366  std::sqrt((satelliteRadius * satelliteRadius) - (m_earthRadius * m_earthRadius));
367 
368  // calculate ratio of the earth and satellite radius
369  m_radiusRatio = m_earthRadius / satelliteRadius;
370 }
371 
372 } // namespace ns3
GeoCoordinate class is used to store and operate with geodetic coordinates.
void SetAltitude(double altitude)
Sets altitude value of coordinate.
double GetAltitude() const
Gets altitude value of coordinate.
double GetLatitude() const
Gets latitude value of coordinate.
ReferenceEllipsoid_t GetRefEllipsoid()
Gets reference ellipsoid used by GeoCoordinate object.
double GetLongitude() const
Gets longitude value of coordinate.
Vector ToVector() const
Converts Geodetic coordinates to Cartesian coordinates.
Ptr< SatMobilityModel > m_geoSatMobility
virtual ~SatMobilityObserver()
Destructor of the mobility observer.
virtual void DoDispose(void)
Dispose of this class instance.
void UpdateElevationAngle()
Update elevation angle.
SatMobilityObserver()
Default constructor of the mobility observer (should not be called)
void ObserveTimingAdvance(Ptr< PropagationDelayModel > ownDelayModel, Ptr< PropagationDelayModel > anotherDelayModel, Ptr< SatMobilityModel > anotherMobility)
Enable observing of the timing advance.
Time GetTimingAdvance(void)
Get timing advance.
void PositionChanged(std::string context, Ptr< const SatMobilityModel > position)
Listener (callback) for mobility position changes.
void SatelliteStatusChanged()
Do actions needed when satellite position is changed.
void UpdateTimingAdvance()
Update timing advance.
double GetVelocity(void)
Get velocity of own movement (speed).
static TypeId GetTypeId(void)
Get the type ID.
Ptr< SatMobilityModel > m_anotherMobility
void NotifyPropertyChange(void) const
Notify listeners about some property is changed.
double GetElevationAngle(void)
Get elevation angle.
TracedCallback< Ptr< const SatMobilityObserver > > m_propertyChangeTrace
Used to alert subscribers that a change in some observed property has occurred.
Ptr< PropagationDelayModel > m_anotherProgDelayModel
Ptr< PropagationDelayModel > m_ownProgDelayModel
Ptr< SatMobilityModel > m_ownMobility
static T RadiansToDegrees(T radian)
Converts radians to degrees.
static T DegreesToRadians(T degree)
Converts degrees to radians.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.