Skip to content

Commit fda77c8

Browse files
committed
Fix t_cg derivative (e.g., Q'(t)) calc & add test
1 parent 6e1f4c7 commit fda77c8

File tree

5 files changed

+106
-50
lines changed

5 files changed

+106
-50
lines changed

Tests/test_cgrs_to_cirs.py

Lines changed: 0 additions & 45 deletions
This file was deleted.

Tests/test_cip_calculation.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ def test_cip_derivatives():
6464
d_cip_s_dt = np.zeros((n,))
6565
d_cip_s_dt_fd = np.zeros((n,))
6666

67-
#dt = Conversions.seconds_to_centuries(1e-4)
6867
dt = 1e-6
6968

7069
for i, val in enumerate(frac):

Tests/test_cirs_to_gcrs.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# This Source Code Form is subject to the terms of the Mozilla Public
2+
# License, v. 2.0. If a copy of the MPL was not distributed with this
3+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
import random
6+
7+
import erfa
8+
import numpy as np
9+
10+
from TerraFrame.PrecessionNutation import SeriesExpansion
11+
from TerraFrame.Utilities import TransformationMatrices, Conversions
12+
from TerraFrame.Utilities.Time import JulianDate
13+
14+
15+
def test_cirs_to_gcrs_calculation():
16+
se_cip_x = SeriesExpansion.cip_x()
17+
se_cip_y = SeriesExpansion.cip_y()
18+
se_cip_sxy2 = SeriesExpansion.cip_sxy2()
19+
20+
val = random.uniform(0, 100.0)
21+
jd_tt = (JulianDate.JulianDate.j2000(
22+
time_scale=JulianDate.TimeScales.TT) + val)
23+
jdc_tt = JulianDate.julian_day_datetime_to_century_datetime(jd_tt)
24+
25+
cip_x = se_cip_x.compute(jdc_tt)
26+
cip_y = se_cip_y.compute(jdc_tt)
27+
sxy2 = se_cip_sxy2.compute(jdc_tt)
28+
cip_s = sxy2 - cip_x * cip_y / 2.0
29+
30+
t_gc = TransformationMatrices.cirs_to_gcrs(cip_x, cip_y, cip_s)
31+
32+
jd1, jd2 = jd_tt.integer_part(), jd_tt.fraction_part()
33+
34+
# Get X, Y, s using IAU 2006/2000A model
35+
x, y, s = erfa.xys06a(jd1, jd2)
36+
37+
# ERFA/SOFA computes the inverse transform, so we need to take the transpose
38+
t_cg_erfa = erfa.c2ixys(x, y, s)
39+
t_gc_erfa = t_cg_erfa.T
40+
41+
assert abs(cip_x - x) < 1e-8
42+
assert abs(cip_y - y) < 1e-8
43+
assert abs(cip_s - s) < 1e-8
44+
45+
assert (np.max(np.abs(t_gc - t_gc_erfa)) < 1e-10)
46+
47+
48+
def test_cirs_to_gcrs_derivative_calculation():
49+
se_cip_x = SeriesExpansion.cip_x()
50+
se_cip_y = SeriesExpansion.cip_y()
51+
se_cip_sxy2 = SeriesExpansion.cip_sxy2()
52+
53+
dt = 1e-6
54+
55+
val = random.uniform(0, 100.0)
56+
jd_tt = (JulianDate.JulianDate.j2000(
57+
time_scale=JulianDate.TimeScales.TT) + val)
58+
jdc_tt = JulianDate.julian_day_datetime_to_century_datetime(jd_tt)
59+
60+
cip_x, d_cip_x_dt = se_cip_x.compute(jdc_tt, derivative=True)
61+
cip_y, d_cip_y_dt = se_cip_y.compute(jdc_tt, derivative=True)
62+
sxy2, d_cip_sxy2_dt = se_cip_sxy2.compute(jdc_tt, derivative=True)
63+
cip_s = sxy2 - cip_x * cip_y / 2.0
64+
d_cip_s_dt = (d_cip_sxy2_dt - 0.5 * cip_y * d_cip_x_dt -
65+
0.5 * cip_x * d_cip_y_dt)
66+
67+
d_t_gc_dt = (TransformationMatrices.
68+
cirs_to_gcrs_derivative(cip_x, cip_y, cip_s,
69+
d_cip_x_dt, d_cip_y_dt, d_cip_s_dt))
70+
71+
cip_x2 = se_cip_x.compute(jdc_tt + dt)
72+
cip_y2 = se_cip_y.compute(jdc_tt + dt)
73+
sxy22 = se_cip_sxy2.compute(jdc_tt + dt)
74+
cip_s2 = sxy22 - cip_x2 * cip_y2 / 2.0
75+
76+
cip_x1 = se_cip_x.compute(jdc_tt - dt)
77+
cip_y1 = se_cip_y.compute(jdc_tt - dt)
78+
sxy21 = se_cip_sxy2.compute(jdc_tt - dt)
79+
cip_s1 = sxy21 - cip_x1 * cip_y1 / 2.0
80+
81+
t_gc2 = TransformationMatrices.cirs_to_gcrs(cip_x2, cip_y2, cip_s2)
82+
t_gc1 = TransformationMatrices.cirs_to_gcrs(cip_x1, cip_y1, cip_s1)
83+
84+
d_t_gc_dt_fd = (t_gc2 - t_gc1) / (2 * dt)
85+
d_t_gc_dt_fd *= Conversions.seconds_to_centuries(1.0)
86+
87+
error = np.abs(d_t_gc_dt - d_t_gc_dt_fd)
88+
89+
assert np.max(error) < 1e-15

src/TerraFrame/CelestialTerrestrial.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def __init__(self, user_polar_motion=True, user_nutation_corrections=True):
3030
self.t_gc = None
3131
self.t_ct = None
3232
self.t_ti = None
33+
self.angular_velocity = None
3334

3435
def itrs_to_gcrs(self, time):
3536
if isinstance(time, datetime.datetime):
@@ -170,7 +171,9 @@ def itrs_to_gcrs_angular_vel(self, time):
170171
dcip_y_dt += ddy_dt
171172

172173
# Create the first transformation matrix
174+
# Q(t)
173175
t_gc = TransformationMatrices.cirs_to_gcrs(cip_x, cip_y, cip_s)
176+
# Q'(t)
174177
dt_gc_dt = (TransformationMatrices
175178
.cirs_to_gcrs_derivative(cip_x, cip_y, cip_s,
176179
dcip_x_dt, dcip_y_dt, dcip_s_dt))
@@ -179,8 +182,10 @@ def itrs_to_gcrs_angular_vel(self, time):
179182
# Intermediate Reference System (TIRS) to the Celestial Intermediate
180183
# Reference System (CIRS): TIRS -> CIRS.
181184
# This function uses normal JD time in UT1.
185+
# R(t)
182186
t_ct = TransformationMatrices.earth_rotation_matrix(jd_ut1)
183187

188+
# R'(t)
184189
dt_ct_dt = (TransformationMatrices
185190
.earth_rotation_matrix_derivative(jd_ut1))
186191

@@ -206,17 +211,24 @@ def itrs_to_gcrs_angular_vel(self, time):
206211
pm_x = TerraFrame.Utilities.Conversions.arcsec_to_rad(pm_x)
207212
pm_y = TerraFrame.Utilities.Conversions.arcsec_to_rad(pm_y)
208213

214+
# W(t)
209215
t_ti = TransformationMatrices.itrs_to_tirs(pm_x, pm_y, sp)
216+
# W'(t)
210217
dt_ti_dt = TransformationMatrices.itrs_to_tirs_derivative(
211218
pm_x, pm_y, sp,
212219
dpm_x_dt, dpm_y_dt, dsp_dt)
213220

214221
# Construct the final transformation matrix: ITRS -> GCRS
222+
# GCRS = Q(t) * R(t) * W(t)
215223
t_gi = t_gc @ t_ct @ t_ti
216224

225+
angular_vel = (t_gc @ t_ct @ dt_ti_dt + t_gc @ dt_ct_dt @ t_ti +
226+
dt_ct_dt @ t_ct @ t_ti)
227+
217228
self.t_gi = t_gi
218229
self.t_gc = t_gc
219230
self.t_ct = t_ct
220231
self.t_ti = t_ti
232+
self.angular_velocity = angular_vel
221233

222-
return t_gi
234+
return t_gi, angular_vel

src/TerraFrame/Utilities/TransformationMatrices.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,10 @@ def cirs_to_gcrs_derivative(x, y, s, dx_dt, dy_dt, ds_dt):
391391
dd_dt = (np.sqrt(-1 - 1/(x**2 + y**2 - 1)) * (x * dx_dt + y * dy_dt) /
392392
(x**2 + y**2))
393393

394-
dt_gc_dt = (r3(-e) @ r2(-d) @ dr3dt(s, ds_dt) +
395-
r3(-e) @ dr2dt(-d, -dd_dt) @ r3(s) +
396-
dr3dt(-e, -de_dt) @ r2(-d) @ r3(s))
394+
dt_gc_dt = (r3(-e) @ r2(-d) @ r3(e) @ dr3dt(s, ds_dt) +
395+
r3(-e) @ r2(-d) @ dr3dt(e, de_dt) @ r3(s) +
396+
r3(-e) @ dr2dt(-d, -dd_dt) @ r3(e) @ r3(s) +
397+
dr3dt(-e, -de_dt) @ r2(-d) @ r3(e) @ r3(s))
397398

398399
return dt_gc_dt
399400

0 commit comments

Comments
 (0)