DME Component Libraries for Java 2024 r2

## Reference Frames and Transformations |

This topic builds upon the foundation of geometrical and coordinate primitives discussed in the
Axes, Points, and Vectors and Coordinates topics.
To begin, we define the geometrical concept of a
ReferenceFrame
as a location point (origin) and a set of axes. A common example of a reference frame is the Earth's fixed frame,
**EarthCentralBody.FixedFrame** (get / set).
In this frame, the
Point
defining the origin is at the center of mass of the Earth and the
Axes are
aligned such that (in Cartesian coordinates) the Z-axis is pointed North and the X-axis intersects the surface
at 0 latitude, 0 longitude. The Y-axis is then defined by the right-hand rule.

Transforming Geometry

GeometryTransformer allows you to easily transform between geometry components by following the chain of relationships between them. One of the primary uses of the transformer is to allow the user to switch between two reference frames. The following example shows how to obtain an evaluator for the transformation between the Earth fixed and Earth inertial reference frames and use it to find an equivalent inertial vector for a given fixed vector:

Java

// Get the Earth central body and assign Earth Orientation Parameters loaded from // the specified EOP data file. EarthCentralBody earth = CentralBodiesFacet.getFromContext().getEarth(); earth.setOrientationParameters(EarthOrientationParametersFile.readData(eopPath)); // Get an evaluator to transform from the fixed to inertial frames, and evaluate it // at 'now' to get the actual transformation. ReferenceFrameEvaluator evaluator = GeometryTransformer.getReferenceFrameTransformation(earth.getFixedFrame(), earth.getInertialFrame()); KinematicTransformation transformation = evaluator.evaluate(JulianDate.getNow(), 0); // Use the transformation to transform a vector in the fixed frame to the inertial frame. Cartesian fixedVectorToTransform = new Cartesian(1.0, 2.0, 3.0); Cartesian equivalentInertialVector = transformation.transform(fixedVectorToTransform);

Each geometry component is defined relative to another geometry component. A
Point is defined in a
ReferenceFrame. A
Vector is defined in a set of
Axes. A set of
Axes or a
ReferenceFrame is defined in terms of another set of
Axes or a
ReferenceFrame, respectively. However, each
Point
is not necessarily defined in terms of the same
ReferenceFrame
all the time. For example, the
Point representing a spacecraft traveling
toward the Moon may initially be defined in an Earth-centered
ReferenceFrame.
As it gets closer to the Moon, it may switch to a Moon-centered
ReferenceFrame.
To handle this, the geometry components' evaluators have a property called
**DefinedInIntervals** (get)
which identifies the
ReferenceFrame or
Axes in which the component is defined
over that interval. In the case of the interplanetary trajectory, the
**DefinedInIntervals** (get)
collection contains two
TimeInterval<ReferenceFrame> objects.
The first holds the Earth-centered
ReferenceFrame in its
**Data** (get) property, and the second holds the Moon-centered
ReferenceFrame as its
**Data** (get).
The first interval stops at the same time the second interval starts, with the
**IsStartIncluded** (get) and
**IsStopIncluded** (get) properties of the
TimeInterval<ReferenceFrame> indicating which system is
used at that time. This allows a single geometry component to be defined in different systems at different times.

In general, it is best to use the
GeometryTransformer
to observe the geometry in the desired system. However, to find the
Axes or
ReferenceFrame
in which a component is defined at a given time, call the
findIntervalContainingDate
method with the
JulianDate used to evaluate the component.
Then, get the
**Data** (get) property of the
TimeInterval<T>.

Each geometry component knows how to evaluate itself with respect to the components held in
**DefinedInIntervals** (get). For example, if a
PointEvaluator is defined in the Earth fixed frame, then calling
evaluate
will return the position and its derivatives with respect to the Earth fixed frame.
To obtain the position, velocity, acceleration, etc. with respect to the Earth inertial frame instead, use the
GeometryTransformer.observePoint
method, as shown in the next example.

Java

// Get the Earth central body and assign Earth Orientation Parameters loaded from // the specified EOP data file. EarthCentralBody earth = CentralBodiesFacet.getFromContext().getEarth(); earth.setOrientationParameters(EarthOrientationParametersFile.readData(eopPath)); // Create a point at a fixed location with respect to the Earth fixed reference frame. PointFixedOffset point = new PointFixedOffset(earth.getFixedFrame(), new Cartesian(8000000.0, 0.0, 0.0)); // Get an evaluator which can transform the point into the Earth inertial // reference frame at a given time. PointEvaluator evaluator = GeometryTransformer.observePoint(point, earth.getInertialFrame()); // Evaluate the evaluator 'now'. The point is stationary with respect to the fixed frame, but // it is moving with respect to the inertial frame. Motion1<Cartesian> positionAndVelocity = evaluator.evaluate(JulianDate.getNow(), 1);

For a Point, the
GeometryTransformer follows the chains created by the
ReferenceFrame in the
**DefinedInIntervals** (get)
to determine the shortest sequence of transformations between any two geometry components. In general,
whenever creating an evaluator to evaluate vector geometry, it is best to get the evaluator through the
GeometryTransformer rather than calling
getEvaluator
on a particular geometry component itself. This ensures that the evaluator computes the geometry in the expected reference system.

Lastly, new geometry components can be easily added by deriving from Axes, Point, or Vector and creating the corresponding AxesEvaluator, PointEvaluator, or VectorEvaluator respectively. These user-defined components can then participate in GeometryTransformer transformations and other geometry types just like the existing components included with DME Component Libraries.

The geometry components can be found in the agi.foundation.geometry package.

International Terrestrial Reference Frames

International Terrestrial Reference Frames (ITRFs) are realizations of the fixed frame of the Earth that are updated periodically by the International Earth Rotation and Reference Systems Service (IERS) to account for plate tectonics and other geophysical phenomena. Because ITRFs have different transformation rules than other ReferenceFrames, converting between ITRFs requires the use of InternationalTerrestrialReferenceFrameTransformers. These transformers require the correct configuration of updated EarthOrientationParameters.

Java

EarthCentralBody earth = CentralBodiesFacet.getFromContext().getEarth(); EarthOrientationParameters eop = EarthOrientationParametersFile.readData(new File(dataPath, "EOP-v1.1.txt").getPath()); earth.setOrientationParameters(eop); // The EarthOrientationParameters of the EarthCentralBody // determine which ITRF is the same as the FixedFrame of the // Earth. By default, this will be the ITRF2020 unless the EarthOrientationParameters // specify otherwise. String nativeItrfFrame = eop.getNativeItrfFrame(); ReferenceFrame itrf2020Frame = earth.getFixedFrame();

There are a number of ways of using ITRF transformers. A possible use case could be the following. Let's say that we have a collection of data in the ITRF2014 frame and we want to transform the collection into the ITRF2020 frame.

Java

// First, get the available transformation definitions. List<InternationalTerrestrialReferenceFrameTransformer> itrfList = InternationalTerrestrialReferenceFrameTransformer.getItrfDefinitions(); // Second, get the ITRF2014 to ITRF2020 frame transformation. InternationalTerrestrialReferenceFrameTransformer itrf2014ToItrf2020 = InternationalTerrestrialReferenceFrameTransformer.getFirstFromList(itrfList, "ITRF2014", "ITRF2020"); // Third, transform the collection. DateMotionCollection1<Cartesian> itrf2020Collection = itrf2014ToItrf2020.transformCollection(itrf2014Collection);

Let's say that instead of transforming the data to create a new collection, we want to create a PointInterpolator from the data. The only ITRF that is also a ReferenceFrame is ITRF2020, which is the fixed frame for the loaded EOP file. createPointInterpolatorInFixedFrame internally transforms the data into the ITRF2020 frame and then creates a point interpolator in the ITRF2020/fixed frame.

Java

final int interpolationDegree = 5; PointInterpolator pointInterpolator = InternationalTerrestrialReferenceFrameTransformer.createPointInterpolatorInFixedFrame(earth, itrf2014ToItrf2020, "ITRF2014", new LagrangePolynomialApproximation(), interpolationDegree, itrf2014Collection);

Points can only be defined in reference frames and the only ITRF frame that is also a
ReferenceFrame
is the one that is equivalent to the
**FixedFrame** (get / set)
of the Earth, which is currently ITRF2020 by default.
convertPoint
can be used to apply ITRF transformations to convert a point from the ITRF2020 to another ITRF.

Java

Point pointItrf2014 = InternationalTerrestrialReferenceFrameTransformer.convertPoint(earth, pointItrf2020, "ITRF2014"); // The converted point can be used to create a collection of ephemeris in the // ITRF2014 frame. The point still needs to be observed in the ITRF2020 frame, // but any data it provides will be correctly transformed into the ITRF2014 frame. EvaluatorGroup group = new EvaluatorGroup(); PointEvaluator evaluator = GeometryTransformer.observePoint(pointItrf2014, itrf2020Frame, group); DateMotionCollection1<Cartesian> newItrf2014Collection = new DateMotionCollection1<Cartesian>(); for (JulianDate date : dates) { Motion1<Cartesian> convertedData = evaluator.evaluate(date, 1); newItrf2014Collection.add(date, convertedData); }