Repository navigation
Implement TEME frame in astropy. #10149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
944c9b7
8db29f2
00d60e4
921872b
426cee2
144bd26
6780557
cd5eefe
3211803
49b6acc
4e8f4bd
7df10e5
c020bfa
0d93ebe
65198bf
5ec9e53
048b443
274467e
9fe06ca
00ecbc6
80233aa
675e025
dcd8fb1
af97427
4c427a4
7e3b428
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # -*- coding: utf-8 -*- | ||
| # Licensed under a 3-clause BSD style license - see LICENSE.rst | ||
| """ | ||
| A coordinate or frame in the TEME (True Equator, Mean Equinox) system. | ||
|
|
||
| TEME is a True equator, Mean Equinox coordinate frame used in NORAD TLE | ||
| satellite files. | ||
|
StuartLittlefair marked this conversation as resolved.
Resolved
|
||
| """ | ||
| # -*- coding: utf-8 -*- | ||
| # Licensed under a 3-clause BSD style license - see LICENSE.rst | ||
|
|
||
| from astropy.utils.decorators import format_doc | ||
| from astropy.coordinates.representation import CartesianRepresentation, CartesianDifferential | ||
| from astropy.coordinates.baseframe import BaseCoordinateFrame, base_doc | ||
| from astropy.coordinates.attributes import TimeAttribute | ||
| from .utils import DEFAULT_OBSTIME | ||
|
|
||
| __all__ = ['TEME'] | ||
|
|
||
| doc_footer_teme = """ | ||
| Other parameters | ||
| ---------------- | ||
| obstime : `~astropy.time.Time` | ||
| The time at which the frame is defined. Used for determining the | ||
| position of the Earth. | ||
| """ | ||
|
|
||
|
|
||
| @format_doc(base_doc, components="", footer=doc_footer_teme) | ||
| class TEME(BaseCoordinateFrame): | ||
| """ | ||
| A coordinate or frame in the True Equator Mean Equinox frame (TEME). | ||
|
|
||
| This frame is a geocentric system similar to CIRS or geocentric apparent place, | ||
| except that the mean sidereal time is used to rotate from TIRS. TEME coordinates | ||
| are most often used in combination with orbital data for satellites in the | ||
| two-line-ephemeris format. | ||
|
|
||
| Different implementations of the TEME frame exist. For clarity, this frame follows the | ||
| conventions and relations to other frames that are set out in Vallado et al (2006). | ||
|
|
||
| For more background on TEME, see the references provided in the | ||
| :ref:`astropy-coordinates-seealso` section of the documentation. | ||
| """ | ||
|
|
||
| default_representation = CartesianRepresentation | ||
| default_differential = CartesianDifferential | ||
|
|
||
| obstime = TimeAttribute() | ||
|
|
||
| # Transformation functions for getting to/from TEME and ITRS are in | ||
| # intermediate rotation transforms.py | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| .. include:: references.txt | ||
|
|
||
| .. _astropy-coordinates-satellites: | ||
|
|
||
| Working with Earth Satellites Using Astropy Coordinates | ||
| ******************************************************* | ||
|
|
||
|
adrn marked this conversation as resolved.
Resolved
|
||
| Satellite data is normally provided in the Two-Line Element (TLE) format | ||
| (see `here <https://www.celestrak.com/NORAD/documentation/tle-fmt.php>`_ | ||
| for a definition). These datasets are designed to be used in combination | ||
| with a theory for orbital propagation model to predict the positions | ||
| of satellites. | ||
|
|
||
| The history of such models is discussed in detail in | ||
| `Vallado et al (2006) <https://celestrak.com/publications/AIAA/2006-6753/AIAA-2006-6753-Rev2.pdf>`_ | ||
| who also provide a reference implementation of the SGP4 orbital propagation | ||
| code, designed to be compatible with the TLE sets provided by the United | ||
| States Department of Defense, which are available from a source like | ||
| `Celestrak <http://celestrak.com/>`_. | ||
|
|
||
| The output coordinate frame of the SGP4 model is the True Equator, Mean Equinox | ||
| frame (TEME), which is one of the frames built-in to `astropy.coordinates`. | ||
| TEME is an Earth-centered inertial frame (i.e., it does not rotate with respect | ||
| to the stars). Several definitions exist; ``astropy`` uses the implementation described | ||
| in `Vallado et al (2006) <https://celestrak.com/publications/AIAA/2006-6753/AIAA-2006-6753-Rev2.pdf>`_. | ||
|
|
||
| Finding TEME Coordinates from TLE Data | ||
| ========================================== | ||
|
|
||
| There is currently no support in `astropy.coordinates` for computing satellite orbits | ||
| from TLE orbital element sets. Full support for handling TLE files is available in | ||
| the `Skyfield <http://rhodesmill.org/skyfield/>`_ library, but some advice for dealing | ||
| with satellite data in ``astropy`` is below. | ||
|
|
||
| .. EXAMPLE START Using sgp4 to get a TEME coordinate | ||
|
|
||
| You will need some external library to compute the position and velocity of the satellite from the | ||
| TLE orbital elements. The `SGP4 <https://pypi.org/project/sgp4/>`_ library can do this. An example | ||
| of using this library to find the `~astropy.coordinates.TEME` coordinates of a satellite is:: | ||
|
|
||
| .. doctest-requires:: sgp4 | ||
|
|
||
| >>> from sgp4.api import Satrec | ||
|
StuartLittlefair marked this conversation as resolved.
Resolved
|
||
| >>> from sgp4.api import SGP4_ERRORS | ||
| >>> s = '1 25544U 98067A 19343.69339541 .00001764 00000-0 38792-4 0 9991' | ||
| >>> t = '2 25544 51.6439 211.2001 0007417 17.6667 85.6398 15.50103472202482' | ||
| >>> satellite = Satrec.twoline2rv(s, t) | ||
|
|
||
| The ``satellite`` object has a method, ``satellite.sgp4``, that will try to compute the TEME position | ||
| and velocity at a given time:: | ||
|
|
||
| .. doctest-requires:: sgp4 | ||
|
|
||
| >>> from astropy.time import Time | ||
| >>> t = Time(2458827.362605, format='jd') | ||
| >>> error_code, teme_p, teme_v = satellite.sgp4(t.jd1, t.jd2) # in km and km/s | ||
| >>> if error_code != 0: | ||
|
StuartLittlefair marked this conversation as resolved.
Resolved
|
||
| ... raise RuntimeError(SGP4_ERRORS[error_code]) | ||
|
|
||
| Now that we have the position and velocity in kilometers and kilometers per second, we can create a | ||
| position in the `~astropy.coordinates.TEME` reference frame:: | ||
|
|
||
| .. doctest-requires:: sgp4 | ||
|
|
||
| >>> from astropy.coordinates import TEME, CartesianDifferential, CartesianRepresentation | ||
| >>> from astropy import units as u | ||
| >>> teme_p = CartesianRepresentation(teme_p*u.km) | ||
| >>> teme_v = CartesianDifferential(teme_v*u.km/u.s) | ||
| >>> teme = TEME(teme_p.with_differentials(teme_v), obstime=t) | ||
|
|
||
| .. EXAMPLE END | ||
|
|
||
| Note how we are careful to set the observed time of the `~astropy.coordinates.TEME` frame to | ||
| the time at which we calculated satellite position. | ||
|
|
||
|
StuartLittlefair marked this conversation as resolved.
Resolved
|
||
| Transforming TEME to Other Coordinate Systems | ||
| ================================================== | ||
|
|
||
|
StuartLittlefair marked this conversation as resolved.
Resolved
|
||
| Once you have satellite positions in `~astropy.coordinates.TEME` coordinates they can be transformed | ||
| into any `astropy.coordinates` frame. | ||
|
|
||
| For example, to find the overhead latitude, longitude, and height of the satellite:: | ||
|
|
||
| .. EXAMPLE START Transforming TEME | ||
|
|
||
| .. doctest-requires:: sgp4 | ||
|
|
||
| >>> from astropy.coordinates import ITRS | ||
| >>> itrs = teme.transform_to(ITRS(obstime=t)) # doctest: +REMOTE_DATA | ||
| >>> location = itrs.earth_location # doctest: +REMOTE_DATA | ||
| >>> location.geodetic # doctest: +REMOTE_DATA +FLOAT_CMP | ||
| GeodeticLocation(lon=<Longitude 160.34199789 deg>, lat=<Latitude -24.6609379 deg>, height=<Quantity 420.17927591 km>) | ||
|
|
||
| Or, if you want to find the altitude and azimuth of the satellite from a particular location:: | ||
|
|
||
| .. doctest-requires:: sgp4 | ||
|
|
||
| >>> from astropy.coordinates import EarthLocation, AltAz | ||
| >>> siding_spring = EarthLocation.of_site('aao') # doctest: +REMOTE_DATA | ||
| >>> aa = teme.transform_to(AltAz(obstime=t, location=siding_spring)) # doctest: +REMOTE_DATA | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. my understanding is that the examples should be standalone. So while this may pass the doctests for now, in the long term it have to be fixed.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK - I've been back and forth on this; no-one seems to know what the right way is!
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the example directive is not working yet, but when it does, these examples will be extracted to a separate place, part of a gallery. I would be very surprised if they see outside of their directive container, but the infra is still in the works, so I cannot say this for certain.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it will probably start with them needing to be stand-alone, but might expand to have ways to see wider context? But anyway, I think it doesn't need to block this PR |
||
| >>> aa.alt # doctest: +REMOTE_DATA +FLOAT_CMP | ||
| <Latitude 10.94798427 deg> | ||
| >>> aa.az # doctest: +REMOTE_DATA +FLOAT_CMP | ||
| <Longitude 59.28807348 deg> | ||
|
|
||
| .. EXAMPLE END | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,6 +52,7 @@ test = | |
| ipython | ||
| coverage | ||
| skyfield>=1.20 | ||
| sgp4 | ||
| all = | ||
| scipy>=0.18 | ||
| dask[array] | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.