Commit 3024143b authored by Pascal Parraud's avatar Pascal Parraud
Browse files

Merge branch 'develop' into bistatic-tdoa

parents a98cefad f88afee6
......@@ -39,6 +39,10 @@
<action dev="bryan" type="add" issue="898">
Added static method to create a BodyFacade from a CenterName.
</action>
<action dev="evan" type="update" issue="903">
Added Frame.getStaticTransformTo(...) and supporting methods to improve
performance.
</action>
</release>
<release version="11.1.1" date="2022-03-17"
description="Version 11.1.1 is a patch release of Orekit.
......
......@@ -31,6 +31,7 @@ import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.frames.FieldTransform;
import org.orekit.frames.Frame;
import org.orekit.frames.StaticTransform;
import org.orekit.frames.Transform;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.FieldAbsoluteDate;
......@@ -104,18 +105,24 @@ public class LofOffsetPointing extends GroundPointing {
final AbsoluteDate shifted = date.shiftedBy(i * h);
// transform from specified reference frame to spacecraft frame
final Transform refToSc =
new Transform(shifted,
new Transform(shifted, pvProv.getPVCoordinates(shifted, frame).negate()),
new Transform(shifted, attitudeLaw.getAttitude(pvProv, shifted, frame).getOrientation()));
final StaticTransform refToSc = StaticTransform.compose(
shifted,
StaticTransform.of(
shifted,
pvProv.getPVCoordinates(shifted, frame).getPosition().negate()),
StaticTransform.of(
shifted,
attitudeLaw.getAttitude(pvProv, shifted, frame).getRotation()));
// transform from specified reference frame to body frame
final Transform refToBody = frame.getTransformTo(shape.getBodyFrame(), shifted);
final StaticTransform refToBody;
if (i == 0) {
centralRefToBody = refToBody;
refToBody = centralRefToBody = frame.getTransformTo(shape.getBodyFrame(), shifted);
} else {
refToBody = frame.getStaticTransformTo(shape.getBodyFrame(), shifted);
}
sample.add(losIntersectionWithBody(new Transform(shifted, refToSc.getInverse(), refToBody)));
sample.add(losIntersectionWithBody(StaticTransform.compose(shifted, refToSc.getInverse(), refToBody)));
}
......@@ -170,7 +177,7 @@ public class LofOffsetPointing extends GroundPointing {
* @param scToBody transform from spacecraft frame to body frame
* @return intersection point in body frame (only the position is set!)
*/
private TimeStampedPVCoordinates losIntersectionWithBody(final Transform scToBody) {
private TimeStampedPVCoordinates losIntersectionWithBody(final StaticTransform scToBody) {
// compute satellite pointing axis and position/velocity in body frame
final Vector3D pointingBodyFrame = scToBody.transformVector(satPointingVector);
......
......@@ -27,6 +27,7 @@ import org.orekit.bodies.FieldGeodeticPoint;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.frames.FieldTransform;
import org.orekit.frames.Frame;
import org.orekit.frames.StaticTransform;
import org.orekit.frames.Transform;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.FieldAbsoluteDate;
......@@ -74,11 +75,11 @@ public class NadirPointing extends GroundPointing {
// sample intersection points in current date neighborhood
final double h = 0.01;
final List<TimeStampedPVCoordinates> sample = new ArrayList<>();
sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(-2 * h), frame), refToBody.shiftedBy(-2 * h)));
sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(-h), frame), refToBody.shiftedBy(-h)));
sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(-2 * h), frame), refToBody.staticShiftedBy(-2 * h)));
sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(-h), frame), refToBody.staticShiftedBy(-h)));
sample.add(nadirRef(pvProv.getPVCoordinates(date, frame), refToBody));
sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(+h), frame), refToBody.shiftedBy(+h)));
sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(+2 * h), frame), refToBody.shiftedBy(+2 * h)));
sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(+h), frame), refToBody.staticShiftedBy(+h)));
sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(+2 * h), frame), refToBody.staticShiftedBy(+2 * h)));
// use interpolation to compute properly the time-derivatives
return TimeStampedPVCoordinates.interpolate(date, CartesianDerivativesFilter.USE_P, sample);
......@@ -112,7 +113,8 @@ public class NadirPointing extends GroundPointing {
* @param refToBody transform from reference frame to body frame
* @return intersection point in body frame (only the position is set!)
*/
private TimeStampedPVCoordinates nadirRef(final TimeStampedPVCoordinates scRef, final Transform refToBody) {
private TimeStampedPVCoordinates nadirRef(final TimeStampedPVCoordinates scRef,
final StaticTransform refToBody) {
final Vector3D satInBodyFrame = refToBody.transformPosition(scRef.getPosition());
......
......@@ -32,6 +32,7 @@ import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitInternalError;
import org.orekit.frames.FieldTransform;
import org.orekit.frames.Frame;
import org.orekit.frames.StaticTransform;
import org.orekit.frames.Transform;
import org.orekit.frames.TransformProvider;
import org.orekit.time.AbsoluteDate;
......@@ -219,6 +220,29 @@ class JPLCelestialBody implements CelestialBody {
}
@Override
public StaticTransform getStaticTransform(final AbsoluteDate date) {
// compute translation from parent frame to self
final PVCoordinates pv = getPVCoordinates(date, definingFrame);
// compute rotation from ICRF frame to self,
// as per the "Report of the IAU/IAG Working Group on Cartographic
// Coordinates and Rotational Elements of the Planets and Satellites"
// These definitions are common for all recent versions of this report
// published every three years, the precise values of pole direction
// and W angle coefficients may vary from publication year as models are
// adjusted. These coefficients are not in this class, they are in the
// specialized classes that do implement the getPole and getPrimeMeridianAngle
// methods
final Vector3D pole = iauPole.getPole(date);
final Vector3D qNode = iauPole.getNode(date);
final Rotation rotation =
new Rotation(pole, qNode, Vector3D.PLUS_K, Vector3D.PLUS_I);
// update transform from parent to self
return StaticTransform.of(date, pv.getPosition().negate(), rotation);
}
/** {@inheritDoc} */
public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
......
......@@ -31,6 +31,7 @@ import org.hipparchus.util.MathArrays;
import org.hipparchus.util.SinCos;
import org.orekit.frames.FieldTransform;
import org.orekit.frames.Frame;
import org.orekit.frames.StaticTransform;
import org.orekit.frames.Transform;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.FieldAbsoluteDate;
......@@ -169,7 +170,8 @@ public class OneAxisEllipsoid extends Ellipsoid implements BodyShape {
final Frame frame, final AbsoluteDate date) {
// transform line and close to body frame
final Transform frameToBodyFrame = frame.getTransformTo(bodyFrame, date);
final StaticTransform frameToBodyFrame =
frame.getStaticTransformTo(bodyFrame, date);
final Line lineInBodyFrame = frameToBodyFrame.transformLine(line);
// compute some miscellaneous variables
......@@ -344,7 +346,7 @@ public class OneAxisEllipsoid extends Ellipsoid implements BodyShape {
public Vector3D projectToGround(final Vector3D point, final AbsoluteDate date, final Frame frame) {
// transform point to body frame
final Transform toBody = frame.getTransformTo(bodyFrame, date);
final StaticTransform toBody = frame.getStaticTransformTo(bodyFrame, date);
final Vector3D p = toBody.transformPosition(point);
final double z = p.getZ();
final double r = FastMath.hypot(p.getX(), p.getY());
......@@ -423,7 +425,8 @@ public class OneAxisEllipsoid extends Ellipsoid implements BodyShape {
public GeodeticPoint transform(final Vector3D point, final Frame frame, final AbsoluteDate date) {
// transform point to body frame
final Vector3D pointInBodyFrame = frame.getTransformTo(bodyFrame, date).transformPosition(point);
final Vector3D pointInBodyFrame = frame.getStaticTransformTo(bodyFrame, date)
.transformPosition(point);
final double r2 = pointInBodyFrame.getX() * pointInBodyFrame.getX() +
pointInBodyFrame.getY() * pointInBodyFrame.getY();
final double r = FastMath.sqrt(r2);
......
......@@ -31,6 +31,7 @@ import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitInternalError;
import org.orekit.errors.OrekitMessages;
import org.orekit.frames.FieldTransform;
import org.orekit.frames.StaticTransform;
import org.orekit.frames.Transform;
import org.orekit.frames.TransformProvider;
import org.orekit.time.AbsoluteDate;
......@@ -242,6 +243,33 @@ public class EstimatedEarthFrameProvider implements TransformProvider {
}
/** {@inheritDoc} */
@Override
public StaticTransform getStaticTransform(final AbsoluteDate date) {
// take parametric prime meridian shift into account
final double theta = linearModel(date, primeMeridianOffsetDriver, primeMeridianDriftDriver);
final StaticTransform meridianShift = StaticTransform.of(
date,
new Rotation(Vector3D.PLUS_K, theta, RotationConvention.FRAME_TRANSFORM)
);
// take parametric pole shift into account
final double xpNeg = -linearModel(date, polarOffsetXDriver, polarDriftXDriver);
final double ypNeg = -linearModel(date, polarOffsetYDriver, polarDriftYDriver);
final StaticTransform poleShift = StaticTransform.compose(
date,
StaticTransform.of(
date,
new Rotation(Vector3D.PLUS_J, xpNeg, RotationConvention.FRAME_TRANSFORM)),
StaticTransform.of(
date,
new Rotation(Vector3D.PLUS_I, ypNeg, RotationConvention.FRAME_TRANSFORM)));
return StaticTransform.compose(date, meridianShift, poleShift);
}
/** {@inheritDoc} */
@Override
public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
......
......@@ -36,6 +36,7 @@ import org.orekit.frames.EOPHistory;
import org.orekit.frames.FieldTransform;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.StaticTransform;
import org.orekit.frames.TopocentricFrame;
import org.orekit.frames.Transform;
import org.orekit.models.earth.displacement.StationDisplacement;
......@@ -411,7 +412,8 @@ public class GroundStation {
final double y = northOffsetDriver.getValue();
final double z = zenithOffsetDriver.getValue();
final BodyShape baseShape = baseFrame.getParentShape();
final Transform baseToBody = baseFrame.getTransformTo(baseShape.getBodyFrame(), date);
final StaticTransform baseToBody =
baseFrame.getStaticTransformTo(baseShape.getBodyFrame(), date);
Vector3D origin = baseToBody.transformPosition(new Vector3D(x, y, z));
if (date != null) {
......@@ -450,7 +452,8 @@ public class GroundStation {
final double y = northOffsetDriver.getValue();
final double z = zenithOffsetDriver.getValue();
final BodyShape baseShape = baseFrame.getParentShape();
final Transform baseToBody = baseFrame.getTransformTo(baseShape.getBodyFrame(), offsetCompensatedDate);
final StaticTransform baseToBody = baseFrame
.getStaticTransformTo(baseShape.getBodyFrame(), offsetCompensatedDate);
Vector3D origin = baseToBody.transformPosition(new Vector3D(x, y, z));
origin = origin.add(computeDisplacement(offsetCompensatedDate, origin));
......@@ -531,7 +534,8 @@ public class GroundStation {
final Gradient y = northOffsetDriver.getValue(freeParameters, indices);
final Gradient z = zenithOffsetDriver.getValue(freeParameters, indices);
final BodyShape baseShape = baseFrame.getParentShape();
final Transform baseToBody = baseFrame.getTransformTo(baseShape.getBodyFrame(), (AbsoluteDate) null);
final StaticTransform baseToBody = baseFrame
.getStaticTransformTo(baseShape.getBodyFrame(), null);
FieldVector3D<Gradient> origin = baseToBody.transformPosition(new FieldVector3D<>(x, y, z));
origin = origin.add(computeDisplacement(offsetCompensatedDate.toAbsoluteDate(), origin.toVector3D()));
......
......@@ -24,7 +24,7 @@ import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.orekit.forces.AbstractForceModel;
import org.orekit.frames.Frame;
import org.orekit.frames.Transform;
import org.orekit.frames.StaticTransform;
import org.orekit.models.earth.atmosphere.Atmosphere;
import org.orekit.propagation.FieldSpacecraftState;
import org.orekit.time.AbsoluteDate;
......@@ -192,7 +192,7 @@ public abstract class AbstractDragForceModel extends AbstractForceModel {
// Get atmosphere properties in atmosphere own frame
final Frame atmFrame = atmosphere.getFrame();
final Transform toBody = frame.getTransformTo(atmFrame, date);
final StaticTransform toBody = frame.getStaticTransformTo(atmFrame, date);
final FieldVector3D<DerivativeStructure> posBodyDS = toBody.transformPosition(position3);
final Vector3D posBody = posBodyDS.toVector3D();
......@@ -261,7 +261,7 @@ public abstract class AbstractDragForceModel extends AbstractForceModel {
// Get atmosphere properties in atmosphere own frame
final Frame atmFrame = atmosphere.getFrame();
final Transform toBody = frame.getTransformTo(atmFrame, date);
final StaticTransform toBody = frame.getStaticTransformTo(atmFrame, date);
final FieldVector3D<Gradient> posBodyDS = toBody.transformPosition(position3);
final Vector3D posBody = posBodyDS.toVector3D();
......
......@@ -38,7 +38,7 @@ import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider.
import org.orekit.forces.gravity.potential.TideSystem;
import org.orekit.forces.gravity.potential.TideSystemProvider;
import org.orekit.frames.Frame;
import org.orekit.frames.Transform;
import org.orekit.frames.StaticTransform;
import org.orekit.propagation.FieldSpacecraftState;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.events.EventDetector;
......@@ -1030,8 +1030,9 @@ public class HolmesFeatherstoneAttractionModel extends AbstractForceModel implem
// get the position in body frame
final AbsoluteDate date = s.getDate();
final Transform fromBodyFrame = bodyFrame.getTransformTo(s.getFrame(), date);
final Transform toBodyFrame = fromBodyFrame.getInverse();
final StaticTransform fromBodyFrame =
bodyFrame.getStaticTransformTo(s.getFrame(), date);
final StaticTransform toBodyFrame = fromBodyFrame.getInverse();
final Vector3D position = toBodyFrame.transformPosition(s.getPVCoordinates().getPosition());
// gradient of the non-central part of the gravity field
......@@ -1066,8 +1067,9 @@ public class HolmesFeatherstoneAttractionModel extends AbstractForceModel implem
// get the position in body frame
final FieldAbsoluteDate<T> date = s.getDate();
final Transform fromBodyFrame = bodyFrame.getTransformTo(s.getFrame(), date.toAbsoluteDate());
final Transform toBodyFrame = fromBodyFrame.getInverse();
final StaticTransform fromBodyFrame =
bodyFrame.getStaticTransformTo(s.getFrame(), date.toAbsoluteDate());
final StaticTransform toBodyFrame = fromBodyFrame.getInverse();
final FieldVector3D<T> position = toBodyFrame.transformPosition(s.getPVCoordinates().getPosition());
// gradient of the non-central part of the gravity field
......@@ -1198,8 +1200,9 @@ public class HolmesFeatherstoneAttractionModel extends AbstractForceModel implem
final int freeParameters = mu.getFreeParameters();
// get the position in body frame
final Transform fromBodyFrame = bodyFrame.getTransformTo(frame, date);
final Transform toBodyFrame = fromBodyFrame.getInverse();
final StaticTransform fromBodyFrame =
bodyFrame.getStaticTransformTo(frame, date);
final StaticTransform toBodyFrame = fromBodyFrame.getInverse();
final Vector3D positionBody = toBodyFrame.transformPosition(position.toVector3D());
// compute gradient and Hessian
......@@ -1274,8 +1277,8 @@ public class HolmesFeatherstoneAttractionModel extends AbstractForceModel implem
final int freeParameters = mu.getFreeParameters();
// get the position in body frame
final Transform fromBodyFrame = bodyFrame.getTransformTo(frame, date);
final Transform toBodyFrame = fromBodyFrame.getInverse();
final StaticTransform fromBodyFrame = bodyFrame.getStaticTransformTo(frame, date);
final StaticTransform toBodyFrame = fromBodyFrame.getInverse();
final Vector3D positionBody = toBodyFrame.transformPosition(position.toVector3D());
// compute gradient and Hessian
......
......@@ -28,7 +28,7 @@ import org.hipparchus.util.FastMath;
import org.orekit.forces.AbstractForceModel;
import org.orekit.frames.FieldTransform;
import org.orekit.frames.Frame;
import org.orekit.frames.Transform;
import org.orekit.frames.StaticTransform;
import org.orekit.propagation.FieldSpacecraftState;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.events.EventDetector;
......@@ -107,7 +107,8 @@ public class LenseThirringRelativity extends AbstractForceModel {
final double r2 = r * r;
// Earth’s angular momentum per unit mass
final Transform t = bodyFrame.getTransformTo(s.getFrame(), s.getDate());
final StaticTransform t =
bodyFrame.getStaticTransformTo(s.getFrame(), s.getDate());
final Vector3D j = t.transformVector(Vector3D.PLUS_K).scalarMultiply(J);
// Eq. 10.12
......
......@@ -134,7 +134,8 @@ public class SmallManeuverAnalyticalModel
j0Dot = null;
// compute maneuver effect on Keplerian (or equinoctial) elements
inertialDV = frame.getTransformTo(state0.getFrame(), state0.getDate()).transformVector(dV);
inertialDV = frame.getStaticTransformTo(state0.getFrame(), state0.getDate())
.transformVector(dV);
// compute mean anomaly change: dM(t1) = dM(t0) + ksi * da * (t1 - t0)
final double mu = state0.getMu();
......
......@@ -249,7 +249,7 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
final Rotation inertial2ThrusterFrame;
if (type.equals(ThrustDirectionAndAttitudeProviderType.DIRECTION_IN_FRAME)) {
inertial2ThrusterFrame = frame.getTransformTo(thrustDirectionFrame, date).getRotation();
inertial2ThrusterFrame = frame.getStaticTransformTo(thrustDirectionFrame, date).getRotation();
} else { // LOF
inertial2ThrusterFrame = thrustDirectionLofType.rotationFromInertial(pvProv.getPVCoordinates(date, frame));
}
......
......@@ -22,6 +22,7 @@ import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative2;
import org.hipparchus.analysis.differentiation.UnivariateDerivative2;
import org.hipparchus.geometry.euclidean.threed.FieldRotation;
import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.RotationConvention;
import org.hipparchus.geometry.euclidean.threed.RotationOrder;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
......@@ -29,6 +30,7 @@ import org.orekit.bodies.CelestialBody;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.FieldAbsoluteDate;
import org.orekit.utils.FieldPVCoordinates;
import org.orekit.utils.TimeStampedPVCoordinates;
/** Transform provider for the rotating frame of the CR3BP System.
* @author Vincent Mouraux
......@@ -82,6 +84,22 @@ class CR3BPRotatingTransformProvider implements TransformProvider {
return new Transform(date, transform2, transform1);
}
/** {@inheritDoc} */
@Override
public StaticTransform getStaticTransform(final AbsoluteDate date) {
final TimeStampedPVCoordinates pv = secondaryBody.getPVCoordinates(date, frame);
final Vector3D translation = Vector3D.PLUS_I
.scalarMultiply(pv.getPosition().getNorm() * mu).negate();
final Rotation rotation = new Rotation(
pv.getPosition(), pv.getMomentum(),
Vector3D.PLUS_I, Vector3D.PLUS_K);
final StaticTransform transform1 = StaticTransform.of(date, translation);
final StaticTransform transform2 = StaticTransform.of(date, rotation);
return StaticTransform.compose(date, transform2, transform1);
}
/** {@inheritDoc} */
@Override
public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
......
......@@ -17,8 +17,11 @@
package org.orekit.frames;
import java.io.Serializable;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.hipparchus.CalculusFieldElement;
import org.hipparchus.Field;
import org.orekit.errors.OrekitIllegalArgumentException;
import org.orekit.errors.OrekitMessages;
import org.orekit.time.AbsoluteDate;
......@@ -240,32 +243,12 @@ public class Frame implements Serializable {
* @return transform from the instance to the destination frame
*/
public Transform getTransformTo(final Frame destination, final AbsoluteDate date) {
if (this == destination) {
// shortcut for special case that may be frequent
return Transform.IDENTITY;
}
// common ancestor to both frames in the frames tree
final Frame common = findCommon(this, destination);
// transform from common to instance
Transform commonToInstance = Transform.IDENTITY;
for (Frame frame = this; frame != common; frame = frame.parent) {
commonToInstance =
new Transform(date, frame.transformProvider.getTransform(date), commonToInstance);
}
// transform from destination up to common
Transform commonToDestination = Transform.IDENTITY;
for (Frame frame = destination; frame != common; frame = frame.parent) {
commonToDestination =
new Transform(date, frame.transformProvider.getTransform(date), commonToDestination);
}
// transform from instance to destination via common
return new Transform(date, commonToInstance.getInverse(), commonToDestination);
return getTransformTo(
destination,
Transform.IDENTITY,
frame -> frame.getTransformProvider().getTransform(date),
(t1, t2) -> new Transform(date, t1, t2),
Transform::getInverse);
}
/** Get the transform from the instance to another frame.
......@@ -275,31 +258,81 @@ public class Frame implements Serializable {
* @return transform from the instance to the destination frame
*/
public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransformTo(final Frame destination, final FieldAbsoluteDate<T> date) {
final Field<T> field = date.getField();
return getTransformTo(
destination,
FieldTransform.getIdentity(field),
frame -> frame.getTransformProvider().getTransform(date),
(t1, t2) -> new FieldTransform<>(date, t1, t2),
FieldTransform::getInverse);
}
/**
* Get the static portion of the transform from the instance to another
* frame. The returned transform is static in the sense that it includes
* translations and rotations, but not rates.
*
* <p>This method is often more performant than {@link
* #getTransformTo(Frame, AbsoluteDate)} when rates are not needed.
*
* @param destination destination frame to which we want to transform
* vectors
* @param date the date (can be null if it is sure than no date
* dependent frame is used)
* @return static transform from the instance to the destination frame
* @since 11.2
*/
public StaticTransform getStaticTransformTo(final Frame destination,
final AbsoluteDate date) {
return getTransformTo(
destination,
StaticTransform.getIdentity(),
frame -> frame.getTransformProvider().getStaticTransform(date),
(t1, t2) -> StaticTransform.compose(date, t1, t2),
StaticTransform::getInverse);
}
/**
* Generic get transform method that builds the transform from {@code this}
* to {@code destination}.
*
* @param destination destination frame to which we want to transform
* vectors
* @param identity transform of the given type.
* @param getTransform method to get a transform from a frame.
* @param compose method to combine two transforms.
* @param inverse method to invert a transform.
* @param <T> Type of transform returned.
* @return composite transform.
*/
private <T> T getTransformTo(final Frame destination,
final T identity,
final Function<Frame, T> getTransform,
final BiFunction<T, T, T> compose,
final Function<T, T> inverse) {
if (this == destination) {
// shortcut for special case that may be frequent
return FieldTransform.getIdentity(date.getField());
return identity;
}
// common ancestor to both frames in the frames tree
final Frame common = findCommon(this, destination);
// transform from common to instance
FieldTransform<T> commonToInstance = FieldTransform.getIdentity(date.getField());
T commonToInstance = identity;
for (Frame frame = this; frame != common; frame = frame.parent) {
commonToInstance =
new FieldTransform<>(date, frame.transformProvider.getTransform(date), commonToInstance);
commonToInstance = compose.apply(getTransform.apply(frame), commonToInstance);
}
// transform from destination up to common
FieldTransform<T> commonToDestination = FieldTransform.getIdentity(date.getField());
T commonToDestination = identity;
for (Frame frame = destination; frame != common; frame = frame.parent) {
commonToDestination =
new FieldTransform<>(date, frame.transformProvider.getTransform(date), commonToDestination);
commonToDestination = compose.apply(getTransform.apply(frame), commonToDestination);
}
// transform from instance to destination via common
return new FieldTransform<>(date, commonToInstance.getInverse(), commonToDestination);
return compose.apply(inverse.apply(commonToInstance), commonToDestination);
}
......
......@@ -123,6 +123,20 @@ public class GTODProvider implements EOPBasedTransformProvider {
}
/** {@inheritDoc} */
@Override
public StaticTransform getStaticTransform(final AbsoluteDate date) {
// compute Greenwich apparent sidereal time, in radians
final double gast = gastFunction.value(date);
// set up the transform from parent TOD
return StaticTransform.of(
date,
new Rotation(Vector3D.PLUS_K, gast, RotationConvention.FRAME_TRANSFORM));
}
/** {@inheritDoc} */
@Override
public <T extends CalculusFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
......