LOFType.java

  1. /* Copyright 2002-2022 CS GROUP
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.frames;

  18. import org.hipparchus.Field;
  19. import org.hipparchus.CalculusFieldElement;
  20. import org.hipparchus.geometry.euclidean.threed.FieldRotation;
  21. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  22. import org.hipparchus.geometry.euclidean.threed.Rotation;
  23. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  24. import org.orekit.time.AbsoluteDate;
  25. import org.orekit.time.FieldAbsoluteDate;
  26. import org.orekit.utils.FieldPVCoordinates;
  27. import org.orekit.utils.PVCoordinates;

  28. /** Enumerate for different types of Local Orbital Frames.
  29.  * @author Luc Maisonobe
  30.  */
  31. public enum LOFType {

  32.     /** Constant for TNW frame
  33.      * (X axis aligned with velocity, Z axis aligned with orbital momentum).
  34.      * <p>
  35.      * The axes of this frame are parallel to the axes of the {@link #VNC}
  36.      * and {@link #NTW} frames:
  37.      * <ul>
  38.      *   <li>X<sub>TNW</sub> =  X<sub>VNC</sub> =  Y<sub>NTW</sub></li>
  39.      *   <li>Y<sub>TNW</sub> = -Z<sub>VNC</sub> = -X<sub>NTW</sub></li>
  40.      *   <li>Z<sub>TNW</sub> =  Y<sub>VNC</sub> =  Z<sub>NTW</sub></li>
  41.      * </ul>
  42.      *
  43.      * @see #VNC
  44.      * @see #NTW
  45.      */
  46.     TNW {

  47.         /** {@inheritDoc} */
  48.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  49.             return new Rotation(pv.getVelocity(), pv.getMomentum(),
  50.                                 Vector3D.PLUS_I, Vector3D.PLUS_K);
  51.         }

  52.         /** {@inheritDoc} */
  53.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  54.                                                                                      final FieldPVCoordinates<T> pv) {
  55.             return new FieldRotation<>(pv.getVelocity(), pv.getMomentum(),
  56.                                        new FieldVector3D<>(field, Vector3D.PLUS_I),
  57.                                        new FieldVector3D<>(field, Vector3D.PLUS_K));
  58.         }

  59.     },

  60.     /** Constant for QSW frame
  61.      * (X axis aligned with position, Z axis aligned with orbital momentum).
  62.      * <p>
  63.      * This frame is also known as the {@link #LVLH} frame, both constants are equivalent.
  64.      * </p>
  65.      * <p>
  66.      * The axes of these frames are parallel to the axes of the {@link #VVLH} frame:
  67.      * <ul>
  68.      *   <li>X<sub>QSW/LVLH</sub> = -Z<sub>VVLH</sub></li>
  69.      *   <li>Y<sub>QSW/LVLH</sub> =  X<sub>VVLH</sub></li>
  70.      *   <li>Z<sub>QSW/LVLH</sub> = -Y<sub>VVLH</sub></li>
  71.      * </ul>
  72.      *
  73.      * @see #LVLH
  74.      * @see #VVLH
  75.      */
  76.     QSW {

  77.         /** {@inheritDoc} */
  78.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  79.             return new Rotation(pv.getPosition(), pv.getMomentum(),
  80.                                 Vector3D.PLUS_I, Vector3D.PLUS_K);
  81.         }

  82.         /** {@inheritDoc} */
  83.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  84.                                                                                      final FieldPVCoordinates<T> pv) {
  85.             return new FieldRotation<>(pv.getPosition(), pv.getMomentum(),
  86.                                        new FieldVector3D<>(field, Vector3D.PLUS_I),
  87.                                        new FieldVector3D<>(field, Vector3D.PLUS_K));
  88.         }

  89.     },

  90.     /** Constant for Local Vertical, Local Horizontal frame
  91.      * (X axis aligned with position, Z axis aligned with orbital momentum).
  92.      * <p>
  93.      * BEWARE! Depending on the background (software used, textbook, community),
  94.      * different incompatible definitions for LVLH are used. This one is consistent
  95.      * with Vallado's book and with AGI's STK. However CCSDS standard, Wertz, and
  96.      * a.i. solutions' FreeFlyer use another definition (see {@link #LVLH_CCSDS}).
  97.      * </p>
  98.      * <p>
  99.      * This frame is also known as the {@link #QSW} frame, both constants are equivalent.
  100.      * </p>
  101.      * <p>
  102.      * The axes of these frames are parallel to the axes of the {@link #LVLH_CCSDS} frame:
  103.      * <ul>
  104.      *   <li>X<sub>LVLH/QSW</sub> = -Z<sub>LVLH_CCSDS</sub></li>
  105.      *   <li>Y<sub>LVLH/QSW</sub> =  X<sub>LVLH_CCSDS</sub></li>
  106.      *   <li>Z<sub>LVLH/QSW</sub> = -Y<sub>LVLH_CCSDS</sub></li>
  107.      * </ul>
  108.      *
  109.      * @see #QSW
  110.      * @see #VVLH
  111.      */
  112.     LVLH {

  113.         /** {@inheritDoc} */
  114.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  115.             return new Rotation(pv.getPosition(), pv.getMomentum(),
  116.                                 Vector3D.PLUS_I, Vector3D.PLUS_K);
  117.         }

  118.         /** {@inheritDoc} */
  119.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  120.                                                                                      final FieldPVCoordinates<T> pv) {
  121.             return new FieldRotation<>(pv.getPosition(), pv.getMomentum(),
  122.                                        new FieldVector3D<>(field, Vector3D.PLUS_I),
  123.                                        new FieldVector3D<>(field, Vector3D.PLUS_K));
  124.         }

  125.     },

  126.     /** Constant for Local Vertical, Local Horizontal frame as defined by CCSDS
  127.      * (Z axis aligned with opposite of position, Y axis aligned with opposite of orbital momentum).
  128.      * <p>
  129.      * BEWARE! Depending on the background (software used, textbook, community),
  130.      * different incompatible definitions for LVLH are used. This one is consistent
  131.      * with CCSDS standard, Wertz, and a.i. solutions' FreeFlyer. However Vallado's
  132.      * book and with AGI's STK use another definition (see {@link #LVLH}).
  133.      * </p>
  134.      * <p>
  135.      * The axes of this frame are parallel to the axes of both the {@link #QSW} and {@link #LVLH} frames:
  136.      * <ul>
  137.      *   <li>X<sub>LVLH_CCSDS/VVLH</sub> =  Y<sub>QSW/LVLH</sub></li>
  138.      *   <li>Y<sub>LVLH_CCSDS/VVLH</sub> = -Z<sub>QSW/LVLH</sub></li>
  139.      *   <li>Z<sub>LVLH_CCSDS/VVLH</sub> = -X<sub>QSW/LVLH</sub></li>
  140.      * </ul>
  141.      *
  142.      * @see #QSW
  143.      * @see #LVLH
  144.      * @since 11.0
  145.      */
  146.     LVLH_CCSDS {

  147.         /** {@inheritDoc} */
  148.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  149.             return new Rotation(pv.getPosition(), pv.getMomentum(),
  150.                                 Vector3D.MINUS_K, Vector3D.MINUS_J);
  151.         }

  152.         /** {@inheritDoc} */
  153.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  154.                                                                                      final FieldPVCoordinates<T> pv) {
  155.             return new FieldRotation<>(pv.getPosition(), pv.getMomentum(),
  156.                                        new FieldVector3D<>(field, Vector3D.MINUS_K),
  157.                                        new FieldVector3D<>(field, Vector3D.MINUS_J));
  158.         }

  159.     },

  160.     /** Constant for Vehicle Velocity, Local Horizontal frame
  161.      * (Z axis aligned with opposite of position, Y axis aligned with opposite of orbital momentum).
  162.      * <p>
  163.      * This is another name for {@link #LVLH_CCSDS}, kept here for compatibility with STK.
  164.      * </p>
  165.      * <p>
  166.      * Beware that the name is misleading: in the general case (i.e. not perfectly circular),
  167.      * none of the axes is perfectly aligned with velocity! The preferred name for this
  168.      * should be {@link #LVLH_CCSDS}.
  169.      * </p>
  170.      * <p>
  171.      * The axes of this frame are parallel to the axes of both the {@link #QSW} and {@link #LVLH} frames:
  172.      * <ul>
  173.      *   <li>X<sub>LVLH_CCSDS/VVLH</sub> =  Y<sub>QSW/LVLH</sub></li>
  174.      *   <li>Y<sub>LVLH_CCSDS/VVLH</sub> = -Z<sub>QSW/LVLH</sub></li>
  175.      *   <li>Z<sub>LVLH_CCSDS/VVLH</sub> = -X<sub>QSW/LVLH</sub></li>
  176.      * </ul>
  177.      * @see #LVLH_CCSDS
  178.      */
  179.     VVLH {

  180.         /** {@inheritDoc} */
  181.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  182.             return LVLH_CCSDS.rotationFromInertial(pv);
  183.         }

  184.         /** {@inheritDoc} */
  185.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  186.                                                                                      final FieldPVCoordinates<T> pv) {
  187.             return LVLH_CCSDS.rotationFromInertial(field, pv);
  188.         }

  189.     },

  190.     /** Constant for Velocity - Normal - Co-normal frame
  191.      * (X axis aligned with velocity, Y axis aligned with orbital momentum).
  192.      * <p>
  193.      * The axes of this frame are parallel to the axes of the {@link #TNW}
  194.      * and {@link #NTW} frames:
  195.      * <ul>
  196.      *   <li>X<sub>VNC</sub> =  X<sub>TNW</sub> = Y<sub>NTW</sub></li>
  197.      *   <li>Y<sub>VNC</sub> =  Z<sub>TNW</sub> = Z<sub>NTW</sub></li>
  198.      *   <li>Z<sub>VNC</sub> = -Y<sub>TNW</sub> = X<sub>NTW</sub></li>
  199.      * </ul>
  200.      *
  201.      * @see #TNW
  202.      * @see #NTW
  203.      */
  204.     VNC {

  205.         /** {@inheritDoc} */
  206.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  207.             return new Rotation(pv.getVelocity(), pv.getMomentum(),
  208.                                 Vector3D.PLUS_I, Vector3D.PLUS_J);
  209.         }

  210.         @Override
  211.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  212.                                                                                      final FieldPVCoordinates<T> pv) {
  213.             return new FieldRotation<>(pv.getVelocity(), pv.getMomentum(),
  214.                                        new FieldVector3D<>(field, Vector3D.PLUS_I),
  215.                                        new FieldVector3D<>(field, Vector3D.PLUS_J));
  216.         }

  217.     },

  218.     /** Constant for Equinoctial Coordinate System
  219.      * (X axis aligned with ascending node, Z axis aligned with orbital momentum).
  220.      * @since 11.0
  221.      */
  222.     EQW {

  223.         /** {@inheritDoc} */
  224.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  225.             final Vector3D m = pv.getMomentum();
  226.             return new Rotation(new Vector3D(-m.getY(), m.getX(), 0), m,
  227.                                 Vector3D.PLUS_I, Vector3D.PLUS_J);
  228.         }

  229.         @Override
  230.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  231.                                                                                      final FieldPVCoordinates<T> pv) {
  232.             final FieldVector3D<T> m = pv.getMomentum();
  233.             return new FieldRotation<>(new FieldVector3D<>(m.getY().negate(), m.getX(), field.getZero()),
  234.                                        m,
  235.                                        new FieldVector3D<>(field, Vector3D.PLUS_I),
  236.                                        new FieldVector3D<>(field, Vector3D.PLUS_J));
  237.         }

  238.     },

  239.     /** Constant for Transverse Velocity Normal coordinate system
  240.      * (Y axis aligned with velocity, Z axis aligned with orbital momentum).
  241.      * <p>
  242.      * The axes of this frame are parallel to the axes of the {@link #TNW}
  243.      * and {@link #VNC} frames:
  244.      * <ul>
  245.      *   <li>X<sub>NTW</sub> = -Y<sub>TNW</sub> = Z<sub>VNC</sub></li>
  246.      *   <li>Y<sub>NTW</sub> =  X<sub>TNW</sub> = X<sub>VNC</sub></li>
  247.      *   <li>Z<sub>NTW</sub> =  Z<sub>TNW</sub> = Y<sub>VNC</sub></li>
  248.      * </ul>
  249.      * @see #TNW
  250.      * @see #VNC
  251.      * @since 11.0
  252.      */
  253.     NTW {

  254.         /** {@inheritDoc} */
  255.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  256.             final Vector3D m = pv.getMomentum();
  257.             return new Rotation(new Vector3D(-m.getY(), m.getX(), 0), m,
  258.                                 Vector3D.PLUS_I, Vector3D.PLUS_J);
  259.         }

  260.         @Override
  261.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  262.                                                                                      final FieldPVCoordinates<T> pv) {
  263.             final FieldVector3D<T> m = pv.getMomentum();
  264.             return new FieldRotation<>(new FieldVector3D<>(m.getY().negate(), m.getX(), field.getZero()),
  265.                                        m,
  266.                                        new FieldVector3D<>(field, Vector3D.PLUS_I),
  267.                                        new FieldVector3D<>(field, Vector3D.PLUS_J));
  268.         }

  269.     };

  270.     /** Get the transform from an inertial frame defining position-velocity and the local orbital frame.
  271.      * @param date current date
  272.      * @param pv position-velocity of the spacecraft in some inertial frame
  273.      * @return transform from the frame where position-velocity are defined to local orbital frame
  274.      */
  275.     public Transform transformFromInertial(final AbsoluteDate date, final PVCoordinates pv) {

  276.         // compute the translation part of the transform
  277.         final Transform translation = new Transform(date, pv.negate());

  278.         // compute the rotation part of the transform
  279.         final Rotation r = rotationFromInertial(pv);
  280.         final Vector3D p = pv.getPosition();
  281.         final Vector3D momentum = pv.getMomentum();
  282.         final Transform rotation =
  283.                 new Transform(date, r, new Vector3D(1.0 / p.getNormSq(), r.applyTo(momentum)));

  284.         return new Transform(date, translation, rotation);

  285.     }

  286.     /** Get the transform from an inertial frame defining position-velocity and the local orbital frame.
  287.      * @param date current date
  288.      * @param pv position-velocity of the spacecraft in some inertial frame
  289.      * @param <T> type of the fiels elements
  290.      * @return transform from the frame where position-velocity are defined to local orbital frame
  291.      * @since 9.0
  292.      */
  293.     public <T extends CalculusFieldElement<T>> FieldTransform<T> transformFromInertial(final FieldAbsoluteDate<T> date,
  294.                                                                                    final FieldPVCoordinates<T> pv) {

  295.         // compute the translation part of the transform
  296.         final FieldTransform<T> translation = new FieldTransform<>(date, pv.negate());

  297.         // compute the rotation part of the transform
  298.         final FieldRotation<T> r = rotationFromInertial(date.getField(), pv);
  299.         final FieldVector3D<T> p = pv.getPosition();
  300.         final FieldVector3D<T> momentum = pv.getMomentum();
  301.         final FieldTransform<T> rotation =
  302.                 new FieldTransform<T>(date, r, new FieldVector3D<>(p.getNormSq().reciprocal(), r.applyTo(momentum)));

  303.         return new FieldTransform<>(date, translation, rotation);

  304.     }

  305.     /** Get the rotation from inertial frame to local orbital frame.
  306.      * <p>
  307.      * This rotation does not include any time derivatives. If first
  308.      * time derivatives (i.e. rotation rate) is needed as well, the full
  309.      * {@link #transformFromInertial(AbsoluteDate, PVCoordinates) transformFromInertial}
  310.      * method must be called and the complete rotation transform must be extracted
  311.      * from it.
  312.      * </p>
  313.      * @param pv position-velocity of the spacecraft in some inertial frame
  314.      * @return rotation from inertial frame to local orbital frame
  315.      */
  316.     public abstract Rotation rotationFromInertial(PVCoordinates pv);

  317.     /** Get the rotation from inertial frame to local orbital frame.
  318.      * <p>
  319.      * This rotation does not include any time derivatives. If first
  320.      * time derivatives (i.e. rotation rate) is needed as well, the full
  321.      * {@link #transformFromInertial(FieldAbsoluteDate, FieldPVCoordinates) transformFromInertial}
  322.      * method must be called and the complete rotation transform must be extracted
  323.      * from it.
  324.      * </p>
  325.      * @param field field to which the elements belong
  326.      * @param pv position-velocity of the spacecraft in some inertial frame
  327.      * @param <T> type of the field elements
  328.      * @return rotation from inertial frame to local orbital frame
  329.      * @since 9.0
  330.      */
  331.     public abstract <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(Field<T> field,
  332.                                                                                           FieldPVCoordinates<T> pv);

  333. }