LOFType.java
- /* Copyright 2002-2025 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.frames;
- import org.hipparchus.CalculusFieldElement;
- import org.hipparchus.Field;
- 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.Vector3D;
- import org.orekit.errors.OrekitException;
- import org.orekit.errors.OrekitMessages;
- import org.orekit.files.ccsds.definitions.OrbitRelativeFrame;
- import org.orekit.time.AbsoluteDate;
- import org.orekit.time.FieldAbsoluteDate;
- import org.orekit.utils.FieldPVCoordinates;
- import org.orekit.utils.PVCoordinates;
- /**
- * Enumerate for different types of Local Orbital Frames.
- *
- * @author Luc Maisonobe
- * @author Maxime Journot
- * @author Vincent Cucchietti
- */
- public enum LOFType implements LOF {
- /** Constant for TNW frame
- * (X axis aligned with velocity, Z axis aligned with orbital momentum).
- * <p>
- * The axes of this frame are parallel to the axes of the {@link #VNC}
- * and {@link #NTW} frames:
- * </p>
- * <ul>
- * <li>X<sub>TNW</sub> = X<sub>VNC</sub> = Y<sub>NTW</sub></li>
- * <li>Y<sub>TNW</sub> = -Z<sub>VNC</sub> = -X<sub>NTW</sub></li>
- * <li>Z<sub>TNW</sub> = Y<sub>VNC</sub> = Z<sub>NTW</sub></li>
- * </ul>
- *
- * @see #VNC
- * @see #NTW
- */
- TNW {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return new Rotation(pv.getVelocity(), pv.getMomentum(),
- Vector3D.PLUS_I, Vector3D.PLUS_K);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return new FieldRotation<>(pv.getVelocity(), pv.getMomentum(),
- new FieldVector3D<>(field, Vector3D.PLUS_I),
- new FieldVector3D<>(field, Vector3D.PLUS_K));
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.TNW;
- }
- },
- /**
- * Constant for TNW frame considered inertial (X axis aligned with velocity, Z axis aligned with orbital momentum).
- * <p>
- * The axes of this frame are parallel to the axes of the {@link #VNC} and {@link #NTW} frames:
- * </p>
- * <ul>
- * <li>X<sub>TNW</sub> = X<sub>VNC</sub> = Y<sub>NTW</sub></li>
- * <li>Y<sub>TNW</sub> = -Z<sub>VNC</sub> = -X<sub>NTW</sub></li>
- * <li>Z<sub>TNW</sub> = Y<sub>VNC</sub> = Z<sub>NTW</sub></li>
- * </ul>
- *
- * @see #VNC
- * @see #NTW
- */
- TNW_INERTIAL {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return TNW.rotationFromInertial(pv);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return TNW.rotationFromInertial(field, pv);
- }
- /** {@inheritDoc} */
- @Override
- public boolean isQuasiInertial() {
- return true;
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.TNW_INERTIAL;
- }
- },
- /** Constant for QSW frame
- * (X axis aligned with position, Z axis aligned with orbital momentum).
- * <p>
- * This frame is also known as the {@link #LVLH} frame, both constants are equivalent.
- * </p>
- * <p>
- * The axes of these frames are parallel to the axes of the {@link #VVLH} frame:
- * </p>
- * <ul>
- * <li>X<sub>QSW/LVLH</sub> = -Z<sub>VVLH</sub></li>
- * <li>Y<sub>QSW/LVLH</sub> = X<sub>VVLH</sub></li>
- * <li>Z<sub>QSW/LVLH</sub> = -Y<sub>VVLH</sub></li>
- * </ul>
- *
- * @see #LVLH
- * @see #VVLH
- */
- QSW {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return new Rotation(pv.getPosition(), pv.getMomentum(),
- Vector3D.PLUS_I, Vector3D.PLUS_K);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return new FieldRotation<>(pv.getPosition(), pv.getMomentum(),
- new FieldVector3D<>(field, Vector3D.PLUS_I),
- new FieldVector3D<>(field, Vector3D.PLUS_K));
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.QSW;
- }
- },
- /**
- * Constant for QSW frame considered inertial (X axis aligned with position, Z axis aligned with orbital momentum).
- * <p>
- * This frame is also known as the {@link #LVLH} frame, both constants are equivalent.
- * </p>
- * <p>
- * The axes of these frames are parallel to the axes of the {@link #VVLH} frame:
- * </p>
- * <ul>
- * <li>X<sub>QSW/LVLH</sub> = -Z<sub>VVLH</sub></li>
- * <li>Y<sub>QSW/LVLH</sub> = X<sub>VVLH</sub></li>
- * <li>Z<sub>QSW/LVLH</sub> = -Y<sub>VVLH</sub></li>
- * </ul>
- *
- * @see #LVLH
- * @see #VVLH
- */
- QSW_INERTIAL {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return QSW.rotationFromInertial(pv);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return QSW.rotationFromInertial(field, pv);
- }
- /** {@inheritDoc} */
- @Override
- public boolean isQuasiInertial() {
- return true;
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.RSW_INERTIAL;
- }
- },
- /** Constant for Local Vertical, Local Horizontal frame
- * (X axis aligned with position, Z axis aligned with orbital momentum).
- * <p>
- * BEWARE! Depending on the background (software used, textbook, community),
- * different incompatible definitions for LVLH are used. This one is consistent
- * with Vallado's book and with AGI's STK. However CCSDS standard, Wertz, and
- * a.i. solutions' FreeFlyer use another definition (see {@link #LVLH_CCSDS}).
- * </p>
- * <p>
- * This frame is also known as the {@link #QSW} frame, both constants are equivalent.
- * </p>
- * <p>
- * The axes of these frames are parallel to the axes of the {@link #LVLH_CCSDS} frame:
- * </p>
- * <ul>
- * <li>X<sub>LVLH/QSW</sub> = -Z<sub>LVLH_CCSDS</sub></li>
- * <li>Y<sub>LVLH/QSW</sub> = X<sub>LVLH_CCSDS</sub></li>
- * <li>Z<sub>LVLH/QSW</sub> = -Y<sub>LVLH_CCSDS</sub></li>
- * </ul>
- *
- * @see #QSW
- * @see #VVLH
- */
- LVLH {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return new Rotation(pv.getPosition(), pv.getMomentum(),
- Vector3D.PLUS_I, Vector3D.PLUS_K);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return new FieldRotation<>(pv.getPosition(), pv.getMomentum(),
- new FieldVector3D<>(field, Vector3D.PLUS_I),
- new FieldVector3D<>(field, Vector3D.PLUS_K));
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- throw new OrekitException(OrekitMessages.CCSDS_DIFFERENT_LVLH_DEFINITION);
- }
- },
- /**
- * Constant for Local Vertical, Local Horizontal frame considered inertial (X axis aligned with position, Z axis
- * aligned with orbital momentum).
- * <p>
- * BEWARE! Depending on the background (software used, textbook, community), different incompatible definitions for
- * LVLH are used. This one is consistent with Vallado's book and with AGI's STK. However CCSDS standard, Wertz, and
- * a.i. solutions' FreeFlyer use another definition (see {@link #LVLH_CCSDS}).
- * </p>
- * <p>
- * This frame is also known as the {@link #QSW} frame, both constants are equivalent.
- * </p>
- * <p>
- * The axes of these frames are parallel to the axes of the {@link #LVLH_CCSDS} frame:
- * </p>
- * <ul>
- * <li>X<sub>LVLH/QSW</sub> = -Z<sub>LVLH_CCSDS</sub></li>
- * <li>Y<sub>LVLH/QSW</sub> = X<sub>LVLH_CCSDS</sub></li>
- * <li>Z<sub>LVLH/QSW</sub> = -Y<sub>LVLH_CCSDS</sub></li>
- * </ul>
- *
- * @see #QSW
- * @see #VVLH
- */
- LVLH_INERTIAL {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return LVLH.rotationFromInertial(pv);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return LVLH.rotationFromInertial(field, pv);
- }
- /** {@inheritDoc} */
- @Override
- public boolean isQuasiInertial() {
- return true;
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- throw new OrekitException(OrekitMessages.CCSDS_DIFFERENT_LVLH_DEFINITION);
- }
- },
- /** Constant for Local Vertical, Local Horizontal frame as defined by CCSDS
- * (Z axis aligned with opposite of position, Y axis aligned with opposite of orbital momentum).
- * <p>
- * BEWARE! Depending on the background (software used, textbook, community),
- * different incompatible definitions for LVLH are used. This one is consistent
- * with CCSDS standard, Wertz, and a.i. solutions' FreeFlyer. However Vallado's
- * book and with AGI's STK use another definition (see {@link #LVLH}).
- * </p>
- * <p>
- * The axes of this frame are parallel to the axes of both the {@link #QSW} and {@link #LVLH} frames:
- * </p>
- * <ul>
- * <li>X<sub>LVLH_CCSDS/VVLH</sub> = Y<sub>QSW/LVLH</sub></li>
- * <li>Y<sub>LVLH_CCSDS/VVLH</sub> = -Z<sub>QSW/LVLH</sub></li>
- * <li>Z<sub>LVLH_CCSDS/VVLH</sub> = -X<sub>QSW/LVLH</sub></li>
- * </ul>
- *
- * @see #QSW
- * @see #LVLH
- * @since 11.0
- */
- LVLH_CCSDS {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return new Rotation(pv.getPosition(), pv.getMomentum(),
- Vector3D.MINUS_K, Vector3D.MINUS_J);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return new FieldRotation<>(pv.getPosition(), pv.getMomentum(),
- new FieldVector3D<>(field, Vector3D.MINUS_K),
- new FieldVector3D<>(field, Vector3D.MINUS_J));
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.LVLH;
- }
- },
- /**
- * Constant for Local Vertical, Local Horizontal frame as defined by CCSDS considered inertial (Z axis aligned with
- * opposite of position, Y axis aligned with opposite of orbital momentum).
- * <p>
- * BEWARE! Depending on the background (software used, textbook, community), different incompatible definitions for
- * LVLH are used. This one is consistent with CCSDS standard, Wertz, and a.i. solutions' FreeFlyer. However
- * Vallado's book and with AGI's STK use another definition (see {@link #LVLH}).
- * </p>
- * <p>
- * The axes of this frame are parallel to the axes of both the {@link #QSW} and {@link #LVLH} frames:
- * </p>
- * <ul>
- * <li>X<sub>LVLH_CCSDS/VVLH</sub> = Y<sub>QSW/LVLH</sub></li>
- * <li>Y<sub>LVLH_CCSDS/VVLH</sub> = -Z<sub>QSW/LVLH</sub></li>
- * <li>Z<sub>LVLH_CCSDS/VVLH</sub> = -X<sub>QSW/LVLH</sub></li>
- * </ul>
- *
- * @see #QSW
- * @see #LVLH
- * @since 11.0
- */
- LVLH_CCSDS_INERTIAL {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return LVLH_CCSDS.rotationFromInertial(pv);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return LVLH_CCSDS.rotationFromInertial(field, pv);
- }
- /** {@inheritDoc} */
- @Override
- public boolean isQuasiInertial() {
- return true;
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.LVLH_INERTIAL;
- }
- },
- /** Constant for Vehicle Velocity, Local Horizontal frame
- * (Z axis aligned with opposite of position, Y axis aligned with opposite of orbital momentum).
- * <p>
- * This is another name for {@link #LVLH_CCSDS}, kept here for compatibility with STK.
- * </p>
- * <p>
- * Beware that the name is misleading: in the general case (i.e. not perfectly circular),
- * none of the axes is perfectly aligned with velocity! The preferred name for this
- * should be {@link #LVLH_CCSDS}.
- * </p>
- * <p>
- * The axes of this frame are parallel to the axes of both the {@link #QSW} and {@link #LVLH} frames:
- * </p>
- * <ul>
- * <li>X<sub>LVLH_CCSDS/VVLH</sub> = Y<sub>QSW/LVLH</sub></li>
- * <li>Y<sub>LVLH_CCSDS/VVLH</sub> = -Z<sub>QSW/LVLH</sub></li>
- * <li>Z<sub>LVLH_CCSDS/VVLH</sub> = -X<sub>QSW/LVLH</sub></li>
- * </ul>
- * @see #LVLH_CCSDS
- */
- VVLH {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return LVLH_CCSDS.rotationFromInertial(pv);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return LVLH_CCSDS.rotationFromInertial(field, pv);
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.LVLH;
- }
- },
- /**
- * Constant for Vehicle Velocity, Local Horizontal frame considered inertial (Z axis aligned with opposite of
- * position, Y axis aligned with opposite of orbital momentum).
- * <p>
- * This is another name for {@link #LVLH_CCSDS}, kept here for compatibility with STK.
- * </p>
- * <p>
- * Beware that the name is misleading: in the general case (i.e. not perfectly circular), none of the axes is
- * perfectly aligned with velocity! The preferred name for this should be {@link #LVLH_CCSDS}.
- * </p>
- * <p>
- * The axes of this frame are parallel to the axes of both the {@link #QSW} and {@link #LVLH} frames:
- * </p>
- * <ul>
- * <li>X<sub>LVLH_CCSDS/VVLH</sub> = Y<sub>QSW/LVLH</sub></li>
- * <li>Y<sub>LVLH_CCSDS/VVLH</sub> = -Z<sub>QSW/LVLH</sub></li>
- * <li>Z<sub>LVLH_CCSDS/VVLH</sub> = -X<sub>QSW/LVLH</sub></li>
- * </ul>
- *
- * @see #LVLH_CCSDS
- */
- VVLH_INERTIAL {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return VVLH.rotationFromInertial(pv);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return VVLH.rotationFromInertial(field, pv);
- }
- /** {@inheritDoc} */
- @Override
- public boolean isQuasiInertial() {
- return true;
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.LVLH_INERTIAL;
- }
- },
- /** Constant for Velocity - Normal - Co-normal frame
- * (X axis aligned with velocity, Y axis aligned with orbital momentum).
- * <p>
- * The axes of this frame are parallel to the axes of the {@link #TNW}
- * and {@link #NTW} frames:
- * </p>
- * <ul>
- * <li>X<sub>VNC</sub> = X<sub>TNW</sub> = Y<sub>NTW</sub></li>
- * <li>Y<sub>VNC</sub> = Z<sub>TNW</sub> = Z<sub>NTW</sub></li>
- * <li>Z<sub>VNC</sub> = -Y<sub>TNW</sub> = X<sub>NTW</sub></li>
- * </ul>
- *
- * @see #TNW
- * @see #NTW
- */
- VNC {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return new Rotation(pv.getVelocity(), pv.getMomentum(),
- Vector3D.PLUS_I, Vector3D.PLUS_J);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return new FieldRotation<>(pv.getVelocity(), pv.getMomentum(),
- new FieldVector3D<>(field, Vector3D.PLUS_I),
- new FieldVector3D<>(field, Vector3D.PLUS_J));
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.VNC_ROTATING;
- }
- },
- /**
- * Constant for Velocity - Normal - Co-normal frame considered inertial (X axis aligned with velocity, Y axis
- * aligned with orbital momentum).
- * <p>
- * The axes of this frame are parallel to the axes of the {@link #TNW} and {@link #NTW} frames:
- * </p>
- * <ul>
- * <li>X<sub>VNC</sub> = X<sub>TNW</sub> = Y<sub>NTW</sub></li>
- * <li>Y<sub>VNC</sub> = Z<sub>TNW</sub> = Z<sub>NTW</sub></li>
- * <li>Z<sub>VNC</sub> = -Y<sub>TNW</sub> = X<sub>NTW</sub></li>
- * </ul>
- *
- * @see #TNW
- * @see #NTW
- */
- VNC_INERTIAL {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return VNC.rotationFromInertial(pv);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return VNC.rotationFromInertial(field, pv);
- }
- /** {@inheritDoc} */
- @Override
- public boolean isQuasiInertial() {
- return true;
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.VNC_INERTIAL;
- }
- },
- /**
- * Constant for Equinoctial Coordinate System (X axis aligned with ascending node, Z axis aligned with orbital
- * momentum).
- *
- * @since 11.0
- */
- EQW {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- final Vector3D m = pv.getMomentum();
- return new Rotation(new Vector3D(-m.getY(), m.getX(), 0), m,
- Vector3D.PLUS_I, Vector3D.PLUS_K);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- final FieldVector3D<T> m = pv.getMomentum();
- return new FieldRotation<>(new FieldVector3D<>(m.getY().negate(), m.getX(), field.getZero()),
- m,
- new FieldVector3D<>(field, Vector3D.PLUS_I),
- new FieldVector3D<>(field, Vector3D.PLUS_K));
- }
- /** {@inheritDoc} */
- @Override
- public boolean isQuasiInertial() {
- return true;
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.EQW_INERTIAL;
- }
- },
- /** Constant for Transverse Velocity Normal coordinate system
- * (Y axis aligned with velocity, Z axis aligned with orbital momentum).
- * <p>
- * The axes of this frame are parallel to the axes of the {@link #TNW}
- * and {@link #VNC} frames:
- * </p>
- * <ul>
- * <li>X<sub>NTW</sub> = -Y<sub>TNW</sub> = Z<sub>VNC</sub></li>
- * <li>Y<sub>NTW</sub> = X<sub>TNW</sub> = X<sub>VNC</sub></li>
- * <li>Z<sub>NTW</sub> = Z<sub>TNW</sub> = Y<sub>VNC</sub></li>
- * </ul>
- * @see #TNW
- * @see #VNC
- * @since 11.0
- */
- NTW {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return new Rotation(pv.getVelocity(), pv.getMomentum(),
- Vector3D.PLUS_J, Vector3D.PLUS_K);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return new FieldRotation<>(pv.getVelocity(), pv.getMomentum(),
- new FieldVector3D<>(field, Vector3D.PLUS_J),
- new FieldVector3D<>(field, Vector3D.PLUS_K));
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.NTW_ROTATING;
- }
- },
- /**
- * Constant for Transverse Velocity Normal coordinate system considered inertial (Y axis aligned with velocity, Z
- * axis aligned with orbital momentum).
- * <p>
- * The axes of this frame are parallel to the axes of the {@link #TNW} and {@link #VNC} frames:
- * </p>
- * <ul>
- * <li>X<sub>NTW</sub> = -Y<sub>TNW</sub> = Z<sub>VNC</sub></li>
- * <li>Y<sub>NTW</sub> = X<sub>TNW</sub> = X<sub>VNC</sub></li>
- * <li>Z<sub>NTW</sub> = Z<sub>TNW</sub> = Y<sub>VNC</sub></li>
- * </ul>
- *
- * @see #TNW
- * @see #VNC
- * @since 11.0
- */
- NTW_INERTIAL {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return NTW.rotationFromInertial(pv);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return NTW.rotationFromInertial(field, pv);
- }
- /** {@inheritDoc} */
- @Override
- public boolean isQuasiInertial() {
- return true;
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return OrbitRelativeFrame.NTW_INERTIAL;
- }
- },
- /**
- * Constant for East-North-Up frame.
- * (Z aligned with position, North Pole in the (+Y, ±Z) half-plane)
- * @see #NED
- * @since 13.0
- */
- ENU {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return new Rotation(pv.getPosition(), east(pv),
- Vector3D.PLUS_K, Vector3D.PLUS_I);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return new FieldRotation<>(pv.getPosition(), east(pv),
- FieldVector3D.getPlusK(field), FieldVector3D.getPlusI(field));
- }
- /** {@inheritDoc} */
- @Override
- public boolean isQuasiInertial() {
- return false;
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return null;
- }
- },
- /**
- * Constant for North-East-Down frame.
- * (Z aligned with opposite of position, North Pole in the (+X, ±Z) half-plane)
- * @see #ENU
- * @since 13.0
- */
- NED {
- /** {@inheritDoc} */
- @Override
- public Rotation rotationFromInertial(final PVCoordinates pv) {
- return new Rotation(pv.getPosition(), east(pv),
- Vector3D.MINUS_K, Vector3D.PLUS_J);
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldPVCoordinates<T> pv) {
- return new FieldRotation<>(pv.getPosition(), east(pv),
- FieldVector3D.getMinusK(field), FieldVector3D.getPlusJ(field));
- }
- /** {@inheritDoc} */
- @Override
- public boolean isQuasiInertial() {
- return false;
- }
- /** {@inheritDoc} */
- @Override
- public OrbitRelativeFrame toOrbitRelativeFrame() {
- return null;
- }
- };
- /** {@inheritDoc} */
- public String getName() {
- return this.name();
- }
- /**
- * Get the rotation from input to output {@link LOFType local orbital frame}.
- * <p>
- * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
- * the full {@link #transformFromLOFInToLOFOut(LOF, LOF, AbsoluteDate, PVCoordinates)} method must be called and
- * the complete rotation transform must be extracted from it.
- *
- * @param in input commonly used local orbital frame
- * @param out output commonly used local orbital frame
- * @param pv position-velocity of the spacecraft in some inertial frame
- *
- * @return rotation from input to output local orbital frame
- */
- static Rotation rotationFromLOFInToLOFOut(final LOFType in, final LOFType out, final PVCoordinates pv) {
- return out.rotationFromLOF(in, pv);
- }
- /**
- * Get the rotation from input to output {@link LOFType local orbital frame}.
- * <p>
- * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
- * the full {@link #transformFromLOFInToLOFOut(LOF, LOF, FieldAbsoluteDate, FieldPVCoordinates)} method must be called and
- * the complete rotation transform must be extracted from it.
- *
- * @param field field to which the elements belong
- * @param in input commonly used local orbital frame
- * @param out output commonly used local orbital frame
- * @param pv position-velocity of the spacecraft in some inertial frame
- * @param <T> type of the field elements
- *
- * @return rotation from input to output local orbital frame
- */
- static <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromLOFInToLOFOut(final Field<T> field,
- final LOFType in,
- final LOFType out,
- final FieldPVCoordinates<T> pv) {
- return out.rotationFromLOF(field, in, pv);
- }
- /**
- * Get the rotation from input {@link LOF local orbital frame} to the instance.
- * <p>
- * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
- * the full {@link #transformFromLOF(LOF, AbsoluteDate, PVCoordinates)} method must be called and the complete rotation
- * transform must be extracted from it.
- *
- * @param fromLOF input local orbital frame
- * @param pv position-velocity of the spacecraft in some inertial frame
- *
- * @return rotation from input local orbital frame to the instance
- */
- public Rotation rotationFromLOF(final LOFType fromLOF, final PVCoordinates pv) {
- // First compute the rotation from the input LOF to the pivot inertial
- final Rotation fromLOFToInertial = fromLOF.rotationFromInertial(pv).revert();
- // Then compute the rotation from the pivot inertial to the output LOF
- final Rotation inertialToThis = this.rotationFromInertial(pv);
- // Output composed rotation
- return fromLOFToInertial.compose(inertialToThis, RotationConvention.FRAME_TRANSFORM);
- }
- /**
- * Get the rotation from input {@link LOFType local orbital frame} to the instance.
- * <p>
- * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
- * the full {@link #transformFromLOF(LOF, FieldAbsoluteDate, FieldPVCoordinates)} method must be called and the complete
- * rotation transform must be extracted from it.
- *
- * @param field field to which the elements belong
- * @param fromLOF input local orbital frame
- * @param pv position-velocity of the spacecraft in some inertial frame
- * @param <T> type of the field elements
- *
- * @return rotation from input local orbital frame to the instance
- */
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromLOF(final Field<T> field,
- final LOFType fromLOF,
- final FieldPVCoordinates<T> pv) {
- // First compute the rotation from the input LOF to the pivot inertial
- final FieldRotation<T> fromLOFToInertial = fromLOF.rotationFromInertial(field, pv).revert();
- // Then compute the rotation from the pivot inertial to the output LOF
- final FieldRotation<T> inertialToThis = this.rotationFromInertial(field, pv);
- // Output composed rotation
- return fromLOFToInertial.compose(inertialToThis, RotationConvention.FRAME_TRANSFORM);
- }
- /**
- * {@inheritDoc} It is unnecessary to use this method when dealing with {@link LOFType}, use
- * {@link #rotationFromInertial(PVCoordinates)} instead.
- */
- @Override
- public Rotation rotationFromInertial(final AbsoluteDate date, final PVCoordinates pv) {
- return rotationFromInertial(pv);
- }
- /**
- * Get the rotation from inertial frame to local orbital frame.
- * <p>
- * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
- * the full {@link #transformFromInertial(AbsoluteDate, PVCoordinates)} method must be called and
- * the complete rotation transform must be extracted from it.
- * </p>
- *
- * @param pv position-velocity of the spacecraft in some inertial frame
- *
- * @return rotation from inertial frame to local orbital frame
- */
- public abstract Rotation rotationFromInertial(PVCoordinates pv);
- /**
- * {@inheritDoc} It is unnecessary to use this method when dealing with {@link LOFType}, use
- * {@link #rotationFromInertial(Field, FieldPVCoordinates)} instead.
- */
- @Override
- public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
- final FieldAbsoluteDate<T> date,
- final FieldPVCoordinates<T> pv) {
- return rotationFromInertial(field, pv);
- }
- /**
- * Get the rotation from inertial frame to local orbital frame.
- * <p>
- * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
- * the full {@link #transformFromInertial(FieldAbsoluteDate, FieldPVCoordinates)} method must be
- * called and the complete rotation transform must be extracted from it.
- * </p>
- *
- * @param field field to which the elements belong
- * @param pv position-velocity of the spacecraft in some inertial frame
- * @param <T> type of the field elements
- *
- * @return rotation from inertial frame to local orbital frame
- */
- public abstract <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(Field<T> field,
- FieldPVCoordinates<T> pv);
- /**
- * Convert current local orbital frame to CCSDS equivalent orbit relative frame when possible, null otherwise.
- *
- * @return CCSDS equivalent orbit relative frame when possible, null otherwise
- *
- * @see OrbitRelativeFrame
- */
- public abstract OrbitRelativeFrame toOrbitRelativeFrame();
- /** Compute East direction.
- * @param pv position-velocity of the spacecraft in some inertial frame
- * @return East direction
- * @since 13.0
- */
- private static Vector3D east(final PVCoordinates pv) {
- final Vector3D p = pv.getPosition();
- final double px = p.getX();
- final double py = p.getY();
- return (px == 0.0 && py == 0.0) ? Vector3D.PLUS_J : new Vector3D(-py, px, 0);
- }
- /** Compute East direction.
- * @param <T> type of the field elements
- * @param pv position-velocity of the spacecraft in some inertial frame
- * @return East direction
- * @since 13.0
- */
- private static <T extends CalculusFieldElement<T>> FieldVector3D<T> east(final FieldPVCoordinates<T> pv) {
- final FieldVector3D<T> p = pv.getPosition();
- final T px = p.getX();
- final T py = p.getY();
- return (px.isZero() && py.isZero()) ?
- FieldVector3D.getPlusJ(px.getField()) :
- new FieldVector3D<>(py.negate(), px, px.getField().getZero());
- }
- }