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 NS_LOG_COMPONENT_DEFINE("SatMobilityObserver");
32 
33 namespace ns3
34 {
35 
36 NS_OBJECT_ENSURE_REGISTERED(SatMobilityObserver);
37 
38 TypeId
40 {
41  static TypeId tid =
42  TypeId("ns3::SatMobilityObserver")
43  .SetParent<Object>()
44  .AddAttribute("OwnMobility",
45  "Own mobility.",
46  PointerValue(),
47  MakePointerAccessor(&SatMobilityObserver::m_ownMobility),
48  MakePointerChecker<SatMobilityModel>())
49  .AddAttribute("SatelliteMobility",
50  "The mobility of the satellite.",
51  PointerValue(),
52  MakePointerAccessor(&SatMobilityObserver::m_geoSatMobility),
53  MakePointerChecker<SatMobilityModel>())
54  .AddAttribute("AnotherMobility",
55  "The mobility of the another end node.",
56  PointerValue(),
57  MakePointerAccessor(&SatMobilityObserver::m_anotherMobility),
58  MakePointerChecker<SatMobilityModel>())
59  .AddAttribute("OwnPropagation",
60  "Own propagation delay model.",
61  PointerValue(),
62  MakePointerAccessor(&SatMobilityObserver::m_ownProgDelayModel),
63  MakePointerChecker<SatMobilityModel>())
64  .AddAttribute("AnotherPropagation",
65  "The propagation delay model of the another end node.",
66  PointerValue(),
68  MakePointerChecker<SatMobilityModel>())
69  .AddAttribute("MinAltitude",
70  "The minimum altitude accepted for own position.",
71  DoubleValue(0),
72  MakeDoubleAccessor(&SatMobilityObserver::m_minAltitude),
73  MakeDoubleChecker<double>())
74  .AddAttribute("MaxAltitude",
75  "The maximum altitude accepted for own position.",
76  DoubleValue(500.00),
77  MakeDoubleAccessor(&SatMobilityObserver::m_maxAltitude),
78  MakeDoubleChecker<double>())
79  .AddTraceSource("PropertyChanged",
80  "The value of the some property has changed",
81  MakeTraceSourceAccessor(&SatMobilityObserver::m_propertyChangeTrace),
82  "ns3::SatMobilityObserver::PropertyChangedCallback");
83  return tid;
84 }
85 
86 TypeId
88 {
89  NS_LOG_FUNCTION(this);
90 
91  return GetTypeId();
92 }
93 
95 {
96  NS_LOG_FUNCTION(this);
97 
98  // this constructor version should not be used
99  NS_ASSERT(false);
100 }
101 
102 SatMobilityObserver::SatMobilityObserver(Ptr<SatMobilityModel> ownMobility,
103  Ptr<SatMobilityModel> geoSatMobility,
104  bool isRegenerative)
105  : m_ownMobility(ownMobility),
106  m_anotherMobility(NULL),
107  m_geoSatMobility(geoSatMobility),
108  m_ownProgDelayModel(NULL),
109  m_anotherProgDelayModel(NULL),
110  m_initialized(false),
111  m_isRegenerative(isRegenerative)
112 {
113  NS_LOG_FUNCTION(this << ownMobility << geoSatMobility);
114 
115  GeoCoordinate satellitePosition = m_geoSatMobility->GetGeoPosition();
116  GeoCoordinate ownPosition = m_ownMobility->GetGeoPosition();
117 
118  // same reference ellipsoide must be used by mobilities
119  NS_ASSERT(satellitePosition.GetRefEllipsoid() == ownPosition.GetRefEllipsoid());
120 
121  double satelliteAltitude = satellitePosition.GetAltitude();
122 
123  // satellite is expected to be in the sky
124  NS_ASSERT(satelliteAltitude > 0.0);
125 
126  // calculate radius of the earth using satellite information
127  m_earthRadius =
128  CalculateDistance(satellitePosition.ToVector(), Vector(0, 0, 0)) - satelliteAltitude;
129 
131  m_updateElevationAngle = true;
132  m_updateTimingAdvance = true;
133  m_timingAdvance_s = Seconds(0);
134 
135  m_geoSatMobility->TraceConnect("SatCourseChange",
136  "Satellite",
137  MakeCallback(&SatMobilityObserver::PositionChanged, this));
138  m_ownMobility->TraceConnect("SatCourseChange",
139  "Own",
140  MakeCallback(&SatMobilityObserver::PositionChanged, this));
141 
142  m_velocity = 0.0;
143 
144  m_initialized = true;
145 }
146 
147 void
149 {
150  NS_LOG_FUNCTION(this);
151 
152  m_ownMobility = NULL;
153  m_anotherMobility = NULL;
154  m_geoSatMobility = NULL;
155  m_ownProgDelayModel = NULL;
157 }
158 
160 {
161  NS_LOG_FUNCTION(this);
162 }
163 
164 void
165 SatMobilityObserver::ObserveTimingAdvance(Ptr<PropagationDelayModel> ownDelayModel,
166  Ptr<PropagationDelayModel> anotherDelayModel,
167  Ptr<SatMobilityModel> anotherMobility)
168 {
169  NS_LOG_FUNCTION(this << ownDelayModel << anotherDelayModel << anotherMobility);
170 
171  NS_ASSERT(ownDelayModel != NULL);
172  NS_ASSERT(anotherDelayModel != NULL);
173  NS_ASSERT(anotherMobility != NULL);
174 
175  auto cb = MakeCallback(&SatMobilityObserver::PositionChanged, this);
176  if (m_anotherMobility != NULL)
177  {
178  m_anotherMobility->TraceDisconnect("SatCourseChange", "Another", cb);
179  }
180 
181  m_ownProgDelayModel = ownDelayModel;
182  m_anotherProgDelayModel = anotherDelayModel;
183  m_anotherMobility = anotherMobility;
184 
185  // same reference ellipsoide must be used by mobilities
186  NS_ASSERT(m_anotherMobility->GetGeoPosition().GetRefEllipsoid() ==
187  m_ownMobility->GetGeoPosition().GetRefEllipsoid());
188 
189  m_anotherMobility->TraceConnect("SatCourseChange", "Another", cb);
190 }
191 
192 double
194 {
195  NS_LOG_FUNCTION(this);
196 
197  if (m_updateElevationAngle == true)
198  {
199  // same reference ellipsoide must be used by mobilities
200  NS_ASSERT(m_geoSatMobility->GetGeoPosition().GetRefEllipsoid() ==
201  m_ownMobility->GetGeoPosition().GetRefEllipsoid());
202 
204  m_updateElevationAngle = false;
205  }
206 
207  return m_elevationAngle;
208 }
209 
210 double
212 {
213  NS_LOG_FUNCTION(this);
214 
215  Vector velocity = m_ownMobility->GetVelocity();
216  m_velocity = std::sqrt((velocity.x * velocity.x) + (velocity.y * velocity.y) +
217  (velocity.z * velocity.z));
218 
219  return m_velocity;
220 }
221 
222 Time
224 {
225  NS_LOG_FUNCTION(this);
226 
227  // update timing advance, if another end is given and update needed
228  if ((m_anotherMobility != NULL) && (m_updateTimingAdvance == true))
229  {
230  // another propagation delay is expected to be given
231  NS_ASSERT(m_anotherProgDelayModel != NULL);
232 
233  // same reference ellipsoide must be used by mobilities
234  NS_ASSERT(m_geoSatMobility->GetGeoPosition().GetRefEllipsoid() ==
235  m_ownMobility->GetGeoPosition().GetRefEllipsoid());
236 
237  // same reference ellipsoide must be used by mobilities
238  NS_ASSERT(m_anotherMobility->GetGeoPosition().GetRefEllipsoid() ==
239  m_ownMobility->GetGeoPosition().GetRefEllipsoid());
240 
242  m_updateTimingAdvance = false;
243  }
244 
245  return m_timingAdvance_s;
246 }
247 
248 void
250 {
251  NS_LOG_FUNCTION(this);
252 
253  if (m_initialized)
254  {
255  m_propertyChangeTrace(this);
256  }
257 }
258 
259 void
260 SatMobilityObserver::PositionChanged(std::string context, Ptr<const SatMobilityModel> position)
261 {
262  NS_LOG_FUNCTION(this << context << position);
263 
264  // set flag on to idicate that elevation angle is needed to update,
265  // when its status is requested with method GetElevationAngle
266  m_updateElevationAngle = true;
267 
268  // set flag on to idicate that timing advance is needed to update,
269  // when its status is requested with method GetTimingAdvance
270  m_updateTimingAdvance = true;
271 
272  // call satellite statis updated routine to update needed variables
273  if (context == "Satellite")
274  {
276  }
277 
279 }
280 
281 void
283 {
284  NS_LOG_FUNCTION(this);
285 
286  m_elevationAngle = NAN;
287 
288  GeoCoordinate ownPosition = m_ownMobility->GetGeoPosition();
289  GeoCoordinate satellitePosition = m_geoSatMobility->GetGeoPosition();
290 
291  NS_ASSERT(ownPosition.GetAltitude() >= m_minAltitude &&
292  ownPosition.GetAltitude() <= m_maxAltitude);
293 
294  // elevation angle is always calculated at earth surface, so set altitude to zero
295  ownPosition.SetAltitude(0);
296 
297  // calculate distance from Earth location to satellite
298  double distanceToSatellite =
299  CalculateDistance(ownPosition.ToVector(), satellitePosition.ToVector());
300 
301  // calculate elevation angle only, if satellite can be seen from own position
302  if (distanceToSatellite <= m_maxDistanceToSatellite)
303  {
304  double earthLatitude = SatUtils::DegreesToRadians(ownPosition.GetLatitude());
305  double satLatitude = SatUtils::DegreesToRadians(satellitePosition.GetLatitude());
306 
307  double earthLongitude = SatUtils::DegreesToRadians(ownPosition.GetLongitude());
308  double satLongitude = SatUtils::DegreesToRadians(satellitePosition.GetLongitude());
309 
310  double longitudeDelta = satLongitude - earthLongitude;
311 
312  // Calculate cosini of the central angle
313  // TODO: Currently we have assumed that the reference ellipsoide is a sphere.
314  // This should be accurate enough for elevation angle calculation with also other
315  // reference ellipsoides. But, if more accurate calculation is needed, then the used
316  // reference ellipsoide is needed to be take into account.
317  double centralAngleCos =
318  (std::cos(earthLatitude) * std::cos(satLatitude) * std::cos(longitudeDelta)) +
319  (std::sin(earthLatitude) * std::sin(satLatitude));
320 
321  // Calculate cosini of the elavation angle
322  double elCos =
323  std::sin(std::acos(centralAngleCos)) /
324  std::sqrt(1 + std::pow(m_radiusRatio, 2) - 2 * m_radiusRatio * centralAngleCos);
325 
326  m_elevationAngle = SatUtils::RadiansToDegrees(std::acos(elCos));
327  }
328 }
329 
330 void
332 {
333  NS_LOG_FUNCTION(this);
334 
335  NS_ASSERT(m_ownProgDelayModel != NULL);
336  NS_ASSERT(m_anotherProgDelayModel != NULL);
337 
338  if (m_isRegenerative)
339  {
341  }
342  else
343  {
346  }
347 }
348 
349 void
351 {
352  NS_LOG_FUNCTION(this);
353 
354  double satelliteAltitude = m_geoSatMobility->GetGeoPosition().GetAltitude();
355 
356  // satellite is expected to be in the sky
357  NS_ASSERT(satelliteAltitude > 0.0);
358 
359  // calculate maximum distance where UT or GW can be on the Earth.
360  double satelliteRadius = satelliteAltitude + m_earthRadius;
362  std::sqrt((satelliteRadius * satelliteRadius) - (m_earthRadius * m_earthRadius));
363 
364  // calculate ratio of the earth and satellite radius
365  m_radiusRatio = m_earthRadius / satelliteRadius;
366 }
367 
368 } // 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.