183 lines
5.8 KiB
Python
183 lines
5.8 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""Raw transforms between coordinate frames, as NumPy matrices."""
|
||
|
||
from numpy import array
|
||
from .constants import ANGVEL, ASEC2RAD, DAY_S, tau
|
||
from .data.spice import inertial_frames as _inertial_frames
|
||
from .functions import mxm, rot_x, rot_z
|
||
|
||
def build_matrix():
|
||
# 'xi0', 'eta0', and 'da0' are ICRS frame biases in arcseconds taken
|
||
# from IERS (2003) Conventions, Chapter 5.
|
||
|
||
xi0 = -0.0166170 * ASEC2RAD
|
||
eta0 = -0.0068192 * ASEC2RAD
|
||
da0 = -0.01460 * ASEC2RAD
|
||
|
||
# Compute elements of rotation matrix.
|
||
|
||
yx = -da0
|
||
zx = xi0
|
||
xy = da0
|
||
zy = eta0
|
||
xz = -xi0
|
||
yz = -eta0
|
||
|
||
# Include second-order corrections to diagonal elements.
|
||
|
||
xx = 1.0 - 0.5 * (yx * yx + zx * zx)
|
||
yy = 1.0 - 0.5 * (yx * yx + zy * zy)
|
||
zz = 1.0 - 0.5 * (zy * zy + zx * zx)
|
||
|
||
return array(((xx, xy, xz), (yx, yy, yz), (zx, zy, zz)))
|
||
|
||
ICRS_to_J2000 = build_matrix()
|
||
del build_matrix
|
||
|
||
_identity = array([(1,0,0), (0,1,0), (0,0,1)])
|
||
|
||
class ICRS(object):
|
||
"""The International Celestial Reference System (ICRS).
|
||
|
||
The ICRS is a permanent reference frame which has replaced J2000,
|
||
with which its axes agree to within 0.02 arcseconds (closer than the
|
||
precision of J2000 itself). The ICRS also supersedes older
|
||
equinox-based systems like B1900 and B1950.
|
||
|
||
"""
|
||
@staticmethod
|
||
def rotation_at(t):
|
||
return _identity
|
||
|
||
class mean_equator_and_equinox_of_date(object):
|
||
"""The coordinate frame of Earth’s mean equator and equinox.
|
||
|
||
This frame is used for measuring right ascension and declination.
|
||
It tracks the Earth’s ‘mean’ equator and equinox which shift slowly
|
||
across the sky due to precession, but ignores the smaller effects of
|
||
nutation.
|
||
|
||
"""
|
||
@staticmethod
|
||
def rotation_at(t):
|
||
return mxm(t.P, ICRS_to_J2000)
|
||
|
||
class true_equator_and_equinox_of_date(object):
|
||
"""The dynamical frame of Earth’s true equator and true equinox of date.
|
||
|
||
This frame is used for measuring right ascension and declination.
|
||
Unlike the fixed reference frames J2000 and the ICRS, this ‘TETE’
|
||
frame rotates slowly as the Earth’s precession and nutation shift
|
||
the equinox point. Unlike the :class:`~skyfield.sgp4lib.TEME`
|
||
frame, this frame doesn’t ignore nutation.
|
||
|
||
This is supplied as an explicit reference frame in case you want
|
||
|xyz| coordinates; if you want angles, it’s better to use the
|
||
standard position method ``radec(epoch='date')`` since that will
|
||
return the conventional units of hours-of-right-ascension instead of
|
||
the degrees-of-longitude that ``frame_latlon()`` would return.
|
||
|
||
This reference frame combines current theories of the Earth’s
|
||
precession and nutation with a small offset between the ITRS and
|
||
J2000 systems to produce right ascension and declination for a given
|
||
date relative to the Earth’s axis and equator of rotation.
|
||
|
||
"""
|
||
@staticmethod
|
||
def rotation_at(t):
|
||
return t.M
|
||
|
||
_itrs_angvel_matrix = array((
|
||
(0.0, DAY_S * ANGVEL, 0.0),
|
||
(-DAY_S * ANGVEL, 0.0, 0.0),
|
||
(0.0, 0.0, 0.0),
|
||
))
|
||
|
||
class tirs(object):
|
||
"""The Terrestrial Intermediate Reference System (TIRS).
|
||
|
||
Coordinates in this Earth-centered Earth-fixed (ECEF) system are
|
||
measured from the axis and equator of the Earth’s rotation, ignoring
|
||
the few tenths of an arcsecond by which the Earth’s actual crust and
|
||
continents might be askance from the axis. (More precisely: like
|
||
the ITRS this frame accounts for precession and nutation, but
|
||
neglects polar motion and the TIO locator.)
|
||
|
||
"""
|
||
@staticmethod
|
||
def rotation_at(t):
|
||
return mxm(rot_z(-t.gast * tau / 24.0), t.M)
|
||
|
||
@staticmethod
|
||
def _dRdt_times_RT_at(t):
|
||
# TODO: taking the derivative of the instantaneous angular
|
||
# velocity provides a more accurate transform.
|
||
return _itrs_angvel_matrix
|
||
|
||
tirs = tirs()
|
||
|
||
class itrs(object):
|
||
"""The International Terrestrial Reference System (ITRS).
|
||
|
||
This is the IAU standard for an Earth-centered Earth-fixed (ECEF)
|
||
coordinate system, anchored to the Earth’s crust and continents.
|
||
This reference frame combines three other reference frames: the
|
||
Earth’s true equator and equinox of date, the Earth’s rotation with
|
||
respect to the stars, and (if your ``Timescale`` has polar offsets
|
||
loaded) the polar wobble of the crust with respect to the Earth’s
|
||
pole of rotation.
|
||
|
||
.. versionadded:: 1.34
|
||
|
||
"""
|
||
@staticmethod
|
||
def rotation_at(t):
|
||
R = mxm(rot_z(-t.gast * tau / 24.0), t.M)
|
||
if t.ts.polar_motion_table is not None:
|
||
R = mxm(t.polar_motion_matrix(), R)
|
||
return R
|
||
|
||
@staticmethod
|
||
def _dRdt_times_RT_at(t):
|
||
# TODO: taking the derivative of the instantaneous angular
|
||
# velocity provides a more accurate transform.
|
||
return _itrs_angvel_matrix
|
||
|
||
itrs = itrs()
|
||
|
||
def build_ecliptic_matrix(t):
|
||
# Build the matrix to rotate an ICRF vector into ecliptic coordinates.
|
||
_, d_eps = t._nutation_angles_radians
|
||
true_obliquity = t._mean_obliquity_radians + d_eps
|
||
return mxm(rot_x(- true_obliquity), t.M)
|
||
|
||
class ecliptic_frame(object):
|
||
"""Reference frame of the true ecliptic and equinox of date."""
|
||
@staticmethod
|
||
def rotation_at(t):
|
||
return build_ecliptic_matrix(t)
|
||
|
||
ecliptic_frame = ecliptic_frame()
|
||
|
||
class InertialFrame(object):
|
||
def __init__(self, doc, matrix):
|
||
self.__doc__ = doc
|
||
self._matrix = matrix
|
||
|
||
def rotation_at(self, t):
|
||
return self._matrix
|
||
|
||
equatorial_B1950_frame = InertialFrame(
|
||
'Reference frame of the Earth’s mean equator and equinox at B1950.',
|
||
_inertial_frames['B1950'],
|
||
)
|
||
|
||
ecliptic_J2000_frame = InertialFrame(
|
||
'Reference frame of the true ecliptic and equinox at J2000.',
|
||
_inertial_frames['ECLIPJ2000'],
|
||
)
|
||
galactic_frame = InertialFrame(
|
||
'Galactic System II reference frame.',
|
||
_inertial_frames['GALACTIC'],
|
||
)
|