[OLD] Orbits and reference frames - poliastro/poliastro GitHub Wiki

All the functionality is already present in poliastro!

Problem

Target: poliastro 0.11

It is unclear what is the reference frame used by Orbit objects, because it's implicit.

Related issues

Explanation

It's a common issue with poliastro that the user wants to:

  • Define orbits in a specific frame, possibly a rotating one, or
  • Know which frame is used specifically, possibly to convert to some other frame

and now there are no good tools for that. It's stated in the docs that

The assumed or implicit reference system is an inertial reference system. For the case of the Solar System, we can consider it to be the International Celestial Reference System or ICRS.

but it's not very clear either.

On the other hand, when Orbit.sample is called, a plain CartesianRepresentation object is returned with no information about the reference frame whatsoever.

More problems:

  • Orbit.from_body_ephem gives orbits in ICRS, but this is almost never the frame of interest for spacecraft, since we want to focus on orbiting around a specific body (the Earth, the Sun).
  • ?

Some ideas for requirements

  • The user shouldn't be able to easily propagate a planet, since this gives incorrect and misleading results with respect to any proper ephemerides (even medium precision ones)
    • Still, the user should be able to easily retrieve orbit data from planets (#313?) as well as to plot them
  • Body objects should be as simple as possible, and in particular they should not store information about their orbit
    • Still, I should have rotational information available somewhere else
  • The result of Orbit.sample should have the appropriate reference frame
  • The user should be able to define an Orbit using data in any reference frame, including rotating ones
    • Still, when propagating, I should be careful not to use data in a rotating frame

Solution

The Orbit constructor methods should accept a frame parameter and choose one depending on the attractor if not given:

ss = Orbit.from_vectors(Sun, r, v)  # frame=HCRS/HeliocentricEclipticJ2000/?
ss = Orbit.from_vectors(Sun, r, v, frame=HCRS(obstime=Time.now()))
ss = Orbit.from_vectors(Sun, r, v, frame=ICRS)  # Notice that the frame might not have the attractor at its center!

What about the epoch parameter? Specifying an epoch and a frame is inconsistent, so we either keep both and make the code fail when both are present, or we remove the epoch parameter completely, possibly using a deprecation warning. I lean towards the latter.

# A DeprecationWarning is raised, informing the user that
# frame has been set to HCRS(obstime=Time.now())
ss = Orbit.from_vectors(Sun, r, v, epoch=Time.now())

On the other hand, Orbit.from_vectors(Sun, ICRS(coords)) should not be allowed, since IMHO they mix frame properties and coordinates in the same object. This makes Orbit objects similar to SkyCoord objects from Astropy.

Note: Still, sometimes poliastro might return a coordinate frame with coordinates.

When propagating, an internal conversion should be done to some default inertial frame:

ss = Orbit.from_vectors(Earth, r, v, frame=ITRS(obstime=Time.now()))

# This converts internally to GCRS to apply the two body equations,
# but the result frame is again ITRS(obstime=Time.now() + 10 * u.s)
ss_after = ss.propagate(10 * u.s)

And properties related to coordinates should be in the proper reference frame:

ss.frame  # ITRS(obstime=Time.now())
ss.sample(10)  # (time, ITRS(obstime=Time.now()))

Note: What to do with ss.r, ss.v and ss.rv()? The way Astropy treats velocities makes returning only v non trivial. We should leave them like that for the time being.

Proposed steps

  1. Introduce inertial frames centered in all the bodies apart from Earth
  • Apparently some reports make use of "XXX-Centered Inertial" notation (Mars-Centered Inertial (MCI), Venus-Centered Inertial and so forth)
  • These frames are not parallel to ICRS but have their own fundamental plane and primary directions, as we already know (see frames.py)
  • Writing them all would probably be more explicit than generating them dynamically with some magic
  • In STK and GMAT there are both inertial, body-specific frames and also frames parallel to the ICRS. There's no specific notation for them.
  1. Add a default (inertial) frame for Orbit objects that depends on the attractor
  • Proper obstime is set using epoch if needed
  • Orbit.from_body_ephem should use ICRS, while we decide whether to keep it or not
  • ss.frame should return this frame
  • ss.sample should return coordinates in this frame
  • What should we do for arbitrary bodies? Probably just return None for the moment
  1. Add the ability to generate a perifocal frame from an Orbit object
  • This has the same intent then the undocumented Orbit.pqw property
  1. Make plotting objects work with these perifocal frames instead of the current trick
  2. Make Orbit.from_vectors accept a frame and deprecate epoch
  • Orbit.propagate should convert to an appropriate frame, propagate, convert back, and create the result Orbit
  • Orbit.from_elements and the rest of the constructors should probably just use an inertial frame, as orbital elements don't make much sense in a rotating frame, but then the signatures might be inconsistent. What to do here?

Other

  • We should replace Orbit.from_body_ephem by something else. This method gives the (wrong) impression that one can reliably propagate the position of the planets, but it's a lie. A paradigmatic example is Orbit.from_body_ephem(Sun). Many people might be using it though, so we must find a proper API for this and raise proper DeprecationWarnings.
  • We should explore the idea of plotting based on frames rather than attractors. This might solve a number of problems, such as trying to plot orbits with different attractors (#204).