Loading...
Searching...
No Matches
satellite-sgp4-mobility-model.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2016 INESC TEC
4 * Copyright (c) 2021 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 * Code from https://gitlab.inesctec.pt/pmms/ns3-satellite
20 *
21 * Author: Pedro Silva <pmms@inesctec.pt>
22 * Author: Bastien Tauran <bastien.tauran@viveris.fr>
23 */
24
26
27#include "vector-extensions.h"
28
29#include "ns3/boolean.h"
30#include "ns3/log.h"
31#include "ns3/simulator.h"
32#include "ns3/string.h"
33
34#include <string>
35#include <utility>
36
37NS_LOG_COMPONENT_DEFINE("SatSGP4MobilityModel");
38
39namespace ns3
40{
41
42NS_OBJECT_ENSURE_REGISTERED(SatSGP4MobilityModel);
43
44const gravconsttype SatSGP4MobilityModel::WGeoSys = wgs72; // recommended for SGP4/SDP4
46
47TypeId
49{
50 static TypeId tid =
51 TypeId("ns3::SatSGP4MobilityModel")
52 .SetParent<SatMobilityModel>()
53 .AddConstructor<SatSGP4MobilityModel>()
54 .AddAttribute("UpdatePositionEachRequest",
55 "Compute position each time a packet is transmitted",
56 BooleanValue(true),
58 MakeBooleanChecker())
59 .AddAttribute(
60 "UpdatePositionPeriod",
61 "Period of satellite position refresh, if UpdatePositionEachRequest is false",
62 TimeValue(Seconds(1)),
64 MakeTimeChecker());
65 return tid;
66}
67
69 : m_startStr("1992-01-01 00:00:00"),
70 m_timeLastUpdate(Time::Min())
71{
72 NS_LOG_FUNCTION(this);
73}
74
75void
77{
78 NS_LOG_FUNCTION(this);
79
80 SatMobilityModel::NotifyConstructionCompleted();
81
83}
84
88
89void
91{
92 NS_LOG_FUNCTION(this << startStr);
93
94 m_startStr = startStr;
96}
97
100{
101 NS_LOG_FUNCTION(this);
102
103 return m_start;
104}
105
106void
108{
109 NS_LOG_FUNCTION(this << t);
110
111 m_start = t;
112}
113
114Vector3D
116{
117 NS_LOG_FUNCTION(this);
118
119 JulianDate cur = m_start + Simulator::Now();
120
121 double r[3], v[3];
122 double delta = (cur - GetTleEpoch()).GetMinutes();
123
124 if (!IsInitialized())
125 {
126 return Vector3D();
127 }
128
129 sgp4(WGeoSys, m_sgp4_record, delta, r, v);
130
131 if (m_sgp4_record.error != 0)
132 {
133 return Vector3D();
134 }
135
136 // velocity vector is in km/s so it needs to be converted to m/s
137 return 1000 * rvTemeTovItrf(Vector3D(r[0], r[1], r[2]), Vector3D(v[0], v[1], v[2]), cur);
138}
139
140Vector
142{
143 NS_LOG_FUNCTION(this);
144
145 return DoGetGeoPosition().ToVector();
146}
147
148void
150{
151 NS_LOG_FUNCTION(this << position);
152
154}
155
158{
159 NS_LOG_FUNCTION(this);
160
161 if ((m_updatePositionEachRequest == false) &&
162 (Simulator::Now() < m_timeLastUpdate + m_updatePositionPeriod))
163 {
164 return m_lastPosition;
165 }
166
167 m_timeLastUpdate = Simulator::Now();
169
170 double r[3], v[3];
171 double delta = (cur - GetTleEpoch()).GetMinutes();
172
173 if (!IsInitialized())
174 {
175 return Vector3D();
176 }
177
178 sgp4(WGeoSys, m_sgp4_record, delta, r, v);
179
180 if (m_sgp4_record.error != 0)
181 {
182 return Vector3D();
183 }
184
185 // vector r is in km so it needs to be converted to meters
186 m_lastPosition = rTemeTorItrf(Vector3D(r[0], r[1], r[2]), cur) * 1000;
187
188 return m_lastPosition;
189}
190
191void
193{
194 NS_LOG_FUNCTION(this << position);
195
196 m_lastPosition = position;
198}
199
200bool
202{
203 NS_LOG_FUNCTION(this);
204
205 return ((m_sgp4_record.jdsatepoch > 0) && (m_tle1 != "") && (m_tle2 != ""));
206}
207
210{
211 NS_LOG_FUNCTION(this);
212
213 if (IsInitialized())
214 {
215 return JulianDate(m_sgp4_record.jdsatepoch);
216 }
217
218 return JulianDate();
219}
220
221void
222SatSGP4MobilityModel::SetTleInfo(const std::string& tle)
223{
224 NS_LOG_FUNCTION(this << tle);
225
226 uint32_t delimPos = tle.find("\n");
227 const std::string line1 = tle.substr(0, delimPos);
228 const std::string line2 = tle.substr(delimPos + 1, tle.size() - delimPos);
229
230 double start, stop, delta;
231 char l1[TleSatInfoWidth + 1], l2[TleSatInfoWidth + 1];
232 double r[3], v[3];
233
234 NS_ASSERT_MSG(line1.size() == TleSatInfoWidth && line2.size() == TleSatInfoWidth,
235 "Two-Line Element info lines must be of length" << TleSatInfoWidth << "!");
236
237 m_tle1 = std::string(line1.c_str());
238 m_tle2 = std::string(line2.c_str());
239
240 memcpy(l1, line1.c_str(), sizeof(l1));
241 memcpy(l2, line2.c_str(), sizeof(l2));
242
243 // 'c' => catalog mode run
244 // 'e' => epoch time (relative to TLE lines)
245 // 'i' => improved mode of operation
246 twoline2rv(l1, l2, 'c', 'e', 'i', WGeoSys, start, stop, delta, m_sgp4_record);
247
248 // call propagator to check if it has been properly initialized
249 sgp4(WGeoSys, m_sgp4_record, 0, r, v);
250
251 if (m_start > GetTleEpoch() + Years(1))
252 {
253 NS_FATAL_ERROR("Simulation start date "
254 << (m_start - GetTleEpoch()).GetDays()
255 << " after TLE epoch. TLE are only valid for a few days");
256 }
257
258 if (m_sgp4_record.error != 0)
259 {
260 NS_FATAL_ERROR("Error while loading TLE file");
261 }
262
264}
265
266Vector3D
267SatSGP4MobilityModel::rTemeTorItrf(const Vector3D& rteme, const JulianDate& t)
268{
269 Matrix pmt = PefToItrf(t); // PEF->ITRF matrix transposed
270 Matrix tmt = TemeToPef(t); // TEME->PEF matrix
271
272 return pmt * (tmt * rteme);
273}
274
275Vector3D
277 const Vector3D& vteme,
278 const JulianDate& t)
279{
280 Matrix pmt = PefToItrf(t); // PEF->ITRF matrix transposed
281 Matrix tmt = TemeToPef(t); // TEME->PEF matrix
282 Vector3D w(0.0, 0.0, t.GetOmegaEarth());
283
284 return pmt * ((tmt * vteme) - CrossProduct(w, tmt * rteme));
285}
286
289{
290 std::pair<double, double> eop = t.GetPolarMotion();
291
292 const double &xp = eop.first, &yp = eop.second;
293 const double cosxp = cos(xp), cosyp = cos(yp);
294 const double sinxp = sin(xp), sinyp = sin(yp);
295
296 // [from AIAA-2006-6753 Report, Page 32, Appendix C - TEME Coordinate System]
297 //
298 // Matrix(ITRF<->PEF) = ROT1(yp)*ROT2(xp) [using c for cos, and s for sin]
299 //
300 // | 1 0 0 |*| c(xp) 0 -s(xp) |=| c(xp) 0 -s(xp) |
301 // | 0 c(yp) s(yp) | | 0 1 0 | | s(yp)*s(xp) c(yp) s(yp)*c(xp) |
302 // | 0 -s(yp) c(yp) | | s(xp) 0 c(xp) | | c(yp)*s(xp) -s(yp) c(yp)*c(xp) |
303 //
304
305 // we return the transpose because it is what's needed
306 return Matrix(cosxp,
307 sinyp * sinxp,
308 cosyp * sinxp,
309 0,
310 cosyp,
311 -sinyp,
312 -sinxp,
313 sinyp * cosxp,
314 cosyp * cosxp);
315}
316
319{
320 const double gmst = t.GetGmst();
321 const double cosg = cos(gmst), sing = sin(gmst);
322
323 // [from AIAA-2006-6753 Report, Page 32, Appendix C - TEME Coordinate System]
324 //
325 // rPEF = ROT3(gmst)*rTEME
326 //
327 // | cos(gmst) sin(gmst) 0 |
328 // | -sin(gmst) cos(gmst) 0 |
329 // | 0 0 1 |
330 //
331
332 return Matrix(cosg, sing, 0, -sing, cosg, 0, 0, 0, 1);
333}
334
336 double c01,
337 double c02,
338 double c10,
339 double c11,
340 double c12,
341 double c20,
342 double c21,
343 double c22)
344{
345 m[0][0] = c00;
346 m[0][1] = c01;
347 m[0][2] = c02;
348 m[1][0] = c10;
349 m[1][1] = c11;
350 m[1][2] = c12;
351 m[2][0] = c20;
352 m[2][1] = c21;
353 m[2][2] = c22;
354}
355
356Vector3D
358{
359 return Vector3D(m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z,
360 m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z,
361 m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z);
362}
363
364} // namespace ns3
GeoCoordinate class is used to store and operate with geodetic coordinates.
Vector ToVector() const
Converts Geodetic coordinates to Cartesian coordinates.
Class to handle Julian days and provide respective Earth Orientation Parameters (EOP).
Definition julian-date.h:79
double GetGmst(void) const
Retrieve the Greenwich Mean Sidereal Time.
double GetOmegaEarth(void) const
Retrieve Earth's angular velocity.
std::pair< double, double > GetPolarMotion(void) const
Retrieve the polar motion cofficients measured/predicted.
SatMobilityModel()
Default constructor.
Keep track of the current position and velocity of satellite using SGP4 model.
std::string m_startStr
Simulation absolute start time in string format.
virtual void DoSetGeoPosition(const GeoCoordinate &position)
static const gravconsttype WGeoSys
World Geodetic System (WGS) constants to be used by SGP4/SDP4 models.
JulianDate GetStartTime() const
Get the time instant considered as the simulation start.
virtual void DoSetPosition(const Vector &position)
static const uint32_t TleSatInfoWidth
Satellite's information line size defined by TLE data format.
virtual void NotifyConstructionCompleted() override
Notifier called once the ObjectBase is fully constructed.
GeoCoordinate m_lastPosition
Last saved satellite position.
void SetStartTime(const JulianDate &t)
Set the time instant considered as the simulation start.
static Matrix PefToItrf(const JulianDate &t)
Retrieve the matrix for converting from PEF to ITRF at a given time.
Time m_updatePositionPeriod
Period of satellite position refresh, if UpdatePositionEachRequest is false.
JulianDate GetTleEpoch(void) const
Retrieve the TLE epoch time.
bool m_updatePositionEachRequest
Compute position each time a packet is transmitted.
elsetrec m_sgp4_record
SGP4/SDP4 record.
static Vector3D rvTemeTovItrf(const Vector3D &rteme, const Vector3D &vteme, const JulianDate &t)
Retrieve the satellite's velocity vector in ITRF coordinates.
static Matrix TemeToPef(const JulianDate &t)
Retrieve the matrix for converting from TEME to PEF at a given time.
Time m_timeLastUpdate
Last position update time.
std::string m_tle2
satellite's TLE data.
static TypeId GetTypeId(void)
Get the type ID.
static Vector3D rTemeTorItrf(const Vector3D &rteme, const JulianDate &t)
Retrieve the satellite's position vector in ITRF coordinates.
void SetStartDate(std::string startStr)
Set the simulation absolute start time in string format.
virtual GeoCoordinate DoGetGeoPosition() const
bool IsInitialized(void) const
Check if the satellite has already been initialized.
void SetTleInfo(const std::string &tle)
Set satellite's TLE information required for its initialization.
JulianDate m_start
Simulation absolute start time.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
Vector3D CrossProduct(const Vector3D &v1, const Vector3D &v2)
Cross product of two Vector3D objects.
void twoline2rv(char longstr1[130], char longstr2[130], char typerun, char typeinput, char opsmode, gravconsttype whichconst, double &startmfe, double &stopmfe, double &deltamin, elsetrec &satrec)
bool sgp4(gravconsttype whichconst, elsetrec &satrec, double tsince, double r[3], double v[3])
gravconsttype
Matrix data structure to make coordinate conversion code clearer and less verbose.
Vector3D operator*(const Vector3D &v) const