NAIA  1.1.1
FrameTransformations.cpp
Go to the documentation of this file.
1 //
2 // Created by vformato on 6/27/23.
3 //
4 // Extracted from gbatch, file CC/FrameTrans.C
5 // Original author: S. Della Torre et al.
6 // Adapted by V. Formato
7 //
8 
9 #include <array>
10 
11 #include <fmt/format.h>
12 #include <fmt/ranges.h>
13 
14 #include <Math/DisplacementVector3D.h>
15 #include <Math/Rotation3D.h>
16 #include <Math/RotationX.h>
17 #include <Math/RotationY.h>
18 #include <Math/RotationZ.h>
19 
21 
22 namespace NAIA {
23 namespace FrameTransformation {
24 
25 double UTCToJulianDate(double utc_time) {
26  // convert UTC time (given in unix time seconds) in JD day
27 
28  // The difference between TAI and UTC is
29  // [INTERNATIONAL EARTH ROTATION AND REFERENCE SYSTEMS SERVICE (IERS) - Bulletin C 43]
30  // from 2009 January 1, 0h UTC, to 2012 July 1 0h UTC : UTC-TAI = - 34s
31  // from 2012 July 1, 0h UTC, until further notice : UTC-TAI = - 35s
32 
33  static constexpr double UTC1Ju2012 = 1341100800; /* unix time of 2012 July 1, 0h UTC*/
34  double TAItime;
35  // convert UTC Time in TAI time, this Difference is a function of the time
36  if (utc_time >= 1483228800)
37  TAItime = utc_time - 37;
38  else if (utc_time >= 1435708800)
39  TAItime = utc_time - 36;
40  else if (utc_time >= UTC1Ju2012)
41  TAItime = utc_time - 35;
42  else
43  TAItime = utc_time - 34;
44 
45  // JD(secconds)=TAI(seconds)+JD_1970*SecondsInADay
46  double JDsec = TAItime + (2440587.5 * 86400);
47  // convert seconds in days
48  return JDsec / 86400;
49 }
50 
51 double GMSTAngle(double utc_time) {
52  // convert from unixtime (UTC) to Julian days
53  double time = UTCToJulianDate(utc_time);
54 
55  // Greenwich mean sidereal time in radians
56 
57  // Interval of time, measured in Julian centuries of 36525 days of UT (mean solar day), elapsed since the epoch 2000
58  // Jan 1d12hUT
59  double T = (time - 2451545.0) / 36525.0;
60  double d = (time - 2451545.0);
61  // greenwich mean sidereal time in degree (i.e. the Greenwich hour angle of the mean equinox of date)
62 
63  // GMST from Meeus, J., 2000. Astronomical Algorithms. Willman-Bell, Richmond,VA, 2nd ed. p 84 (eq.11-4) adapted from
64  // IDL procedure http://idlastro.gsfc.nasa.gov/ftp/pro/astro/ct2lst.pro
65  double GMST_deg = std::fmod((280.46061837 + 360.98564736629 * d + T * T * (0.000387933 - T / 38710000.0)), 360);
66 
67  double GMSTrad = GMST_deg * pi / 180.; /* greenwich mean sidereal time in radians*/
68  return GMSTrad;
69 }
70 
72 //
73 // double degree_to_Rad(double angDeg){
75 // return angDeg/180.*pi;
76 // }
77 // double rad_to_degree(double angRad){
79 // return angRad*180./pi;
80 // }
81 //
83 // void FT_Cart2Angular(double x, double y, double z, double& r, double& theta, double& phi){
84 // /* convert cartesian coordinates into spherical coordinates
85 // theta is the latitude (i.e. the angle with the equator plane
86 // phi is the aziutal angle*/
87 // r=sqrt(x*x+y*y+z*z);
88 // phi=atan2(y,x);
89 // theta=pi/2.-acos(z/r);
90 // }
91 
93  // Get rotation angle for the Greenwich meridian in GTOD ref frame
94  float gmt_angle = GMSTAngle(time);
95 
96  auto rotation = ROOT::Math::RotationZ(gmt_angle);
97 
98  return CartesianCoo<RefFrame::ECI>{rotation(coo).Coordinates()};
99 }
100 
102  double time) {
103  // Get rotation angle for the Greenwich meridian in GTOD ref frame
104  float gmt_angle = GMSTAngle(time);
105 
106  auto rotation = ROOT::Math::RotationZ(gmt_angle);
107 
108  CartesianCoo<RefFrame::ECI> result{rotation(vel).Coordinates()};
109 
110  // Add Earth rotation contribution
111  static constexpr double omega = 2.0 * pi / 86400.0;
112 
113  result.SetCoordinates(result.X() * std::cos(gmt_angle) - result.Y() * std::sin(gmt_angle) +
114  omega * (-coo.Y() * std::cos(gmt_angle) - coo.X() * std::sin(gmt_angle)),
115  result.X() * std::sin(gmt_angle) + result.Y() * std::cos(gmt_angle) +
116  omega * (coo.X() * std::cos(gmt_angle) - coo.Y() * std::sin(gmt_angle)),
117  result.Z());
118  return result;
119 }
120 
122  static constexpr double AMS_angle = 12.0001 * pi / 180.0;
123 
124  auto rotation = ROOT::Math::RotationY(AMS_angle);
125 
126  CartesianCoo<RefFrame::ISSBody> result{rotation(coo).Coordinates()};
127  // TODO: check this transformation: how is ISSBody defined? And then can we express it as a rotation or set of
128  // rotations?
129  result.SetCoordinates(-1 * result.Y(), -1 * result.X(), -1 * result.Z());
130 
131  return result;
132 }
133 
135  double ISSRoll) {
136  // rotation along X axis
137  auto roll_rotation = ROOT::Math::RotationX(ISSRoll);
138  coo = roll_rotation(coo);
139 
140  // rotation along Y axis
141  auto pitch_rotation = ROOT::Math::RotationY(ISSPitch);
142  coo = pitch_rotation(coo);
143 
144  // rotation along Z axis
145  auto yaw_rotation = ROOT::Math::RotationZ(ISSYaw);
146  coo = yaw_rotation(coo);
147 
148  return CartesianCoo<RefFrame::ISSLVLH>{coo.Coordinates()};
149 }
150 
152  CartesianCoo<RefFrame::ECI> ISSECIVel) {
153  // 1st step: normalize ISS position and velocity
154  ISSECIPos /= std::sqrt(ISSECIPos.mag2());
155  ISSECIVel /= std::sqrt(ISSECIVel.mag2());
156 
157  // 2nd step: create the martix R_m elements
158 
159  // NOTE: from the original definition:
160  // the matrix of transformation is given by three lines X_v, Y_v, Z_v of 3 elements each
161  // | X_v | | Y_v x Z_v |
162  // | Y_v | = | V_v x R_v | = R_m
163  // | Z_v | | -R_v |
164 
165  // NOTE: X_v, Y_v, Z_v vectors must be unitary
166  auto Z_v = ISSECIPos * -1.0;
167  auto Y_v = ISSECIVel.Cross(
168  ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<double>, RFrame<RefFrame::ECI>>{ISSECIPos});
169  Y_v /= std::sqrt(Y_v.mag2());
170  auto X_v = Y_v.Cross(ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<double>, RFrame<RefFrame::ECI>>{Z_v});
171  X_v /= std::sqrt(X_v.mag2());
172 
173  // NOTE: this constructor places the three vectors as the columns of the matrix. The original definition is given in
174  // terms of the matrix rows so we don't need to transpose it.
175  auto R_m = ROOT::Math::Rotation3D{X_v, Y_v, Z_v};
176  TMatrixT<double> m{3, 3};
177  R_m.GetRotationMatrix(m);
178 
179  return CartesianCoo<RefFrame::ECI>{R_m(coo).Coordinates()};
180 }
181 
183  double time) { // Get rotation angle for the Greenwich meridian in GTOD ref frame
184  float gmt_angle = GMSTAngle(time);
185 
186  auto rotation = ROOT::Math::RotationZ(-1.0 * gmt_angle);
187 
188  return CartesianCoo<RefFrame::GTOD>{rotation(coo).Coordinates()};
189 }
190 
191 } // namespace FrameTransformation
192 } // namespace NAIA
NAIA::FrameTransformation::ISSBodyToLVLH
CartesianCoo< RefFrame::ISSLVLH > ISSBodyToLVLH(CartesianCoo< RefFrame::ISSBody > coo, double ISSYaw, double ISSPitch, double ISSRoll)
Definition: FrameTransformations.cpp:134
NAIA::FrameTransformation::GTODToECIPos
CartesianCoo< RefFrame::ECI > GTODToECIPos(CartesianCoo< RefFrame::GTOD > coo, double time)
‍** **************** COMMON *******************************‍/
Definition: FrameTransformations.cpp:92
NAIA::FrameTransformation::UTCToJulianDate
double UTCToJulianDate(double utc_time)
Definition: FrameTransformations.cpp:25
FrameTransformations.h
NAIA
Definition: Event.h:13
NAIA::FrameTransformation::AMSLocalToISSBody
CartesianCoo< RefFrame::ISSBody > AMSLocalToISSBody(CartesianCoo< RefFrame::AMSLocal > coo)
Definition: FrameTransformations.cpp:121
NAIA::FrameTransformation::ISSLVLHToECI
CartesianCoo< RefFrame::ECI > ISSLVLHToECI(CartesianCoo< RefFrame::ISSLVLH > coo, CartesianCoo< RefFrame::ECI > ISSECIPos, CartesianCoo< RefFrame::ECI > ISSECIVel)
Definition: FrameTransformations.cpp:151
NAIA::FrameTransformation::ECIToGTOD
CartesianCoo< RefFrame::GTOD > ECIToGTOD(CartesianCoo< RefFrame::ECI > coo, double time)
Definition: FrameTransformations.cpp:182
NAIA::FrameTransformation::RFrame
Definition: FrameTransformations.h:26
NAIA::FrameTransformation::pi
constexpr double pi
Definition: FrameTransformations.h:17
NAIA::FrameTransformation::GMSTAngle
double GMSTAngle(double utc_time)
Definition: FrameTransformations.cpp:51
NAIA::FrameTransformation::CartesianCoo
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, RFrame< Frame > > CartesianCoo
Definition: FrameTransformations.h:29
NAIA::FrameTransformation::GTODToECIVel
CartesianCoo< RefFrame::ECI > GTODToECIVel(CartesianCoo< RefFrame::GTOD > vel, CartesianCoo< RefFrame::GTOD > coo, double time)
Definition: FrameTransformations.cpp:101