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.CalculusFieldElement;
  19. import org.hipparchus.Field;
  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.RotationConvention;
  24. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  25. import org.orekit.time.AbsoluteDate;
  26. import org.orekit.time.FieldAbsoluteDate;
  27. import org.orekit.utils.FieldPVCoordinates;
  28. import org.orekit.utils.PVCoordinates;

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

  35.     /** Constant for TNW frame
  36.      * (X axis aligned with velocity, Z axis aligned with orbital momentum).
  37.      * <p>
  38.      * The axes of this frame are parallel to the axes of the {@link #VNC}
  39.      * and {@link #NTW} frames:
  40.      * <ul>
  41.      *   <li>X<sub>TNW</sub> =  X<sub>VNC</sub> =  Y<sub>NTW</sub></li>
  42.      *   <li>Y<sub>TNW</sub> = -Z<sub>VNC</sub> = -X<sub>NTW</sub></li>
  43.      *   <li>Z<sub>TNW</sub> =  Y<sub>VNC</sub> =  Z<sub>NTW</sub></li>
  44.      * </ul>
  45.      *
  46.      * @see #VNC
  47.      * @see #NTW
  48.      */
  49.     TNW {
  50.         /** {@inheritDoc} */
  51.         @Override
  52.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  53.             return new Rotation(pv.getVelocity(), pv.getMomentum(),
  54.                                 Vector3D.PLUS_I, Vector3D.PLUS_K);
  55.         }

  56.         /** {@inheritDoc} */
  57.         @Override
  58.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  59.                                                                                          final FieldPVCoordinates<T> pv) {
  60.             return new FieldRotation<>(pv.getVelocity(), pv.getMomentum(),
  61.                                        new FieldVector3D<>(field, Vector3D.PLUS_I),
  62.                                        new FieldVector3D<>(field, Vector3D.PLUS_K));
  63.         }

  64.     },

  65.     /** Constant for QSW frame
  66.      * (X axis aligned with position, Z axis aligned with orbital momentum).
  67.      * <p>
  68.      * This frame is also known as the {@link #LVLH} frame, both constants are equivalent.
  69.      * </p>
  70.      * <p>
  71.      * The axes of these frames are parallel to the axes of the {@link #VVLH} frame:
  72.      * <ul>
  73.      *   <li>X<sub>QSW/LVLH</sub> = -Z<sub>VVLH</sub></li>
  74.      *   <li>Y<sub>QSW/LVLH</sub> =  X<sub>VVLH</sub></li>
  75.      *   <li>Z<sub>QSW/LVLH</sub> = -Y<sub>VVLH</sub></li>
  76.      * </ul>
  77.      *
  78.      * @see #LVLH
  79.      * @see #VVLH
  80.      */
  81.     QSW {
  82.         /** {@inheritDoc} */
  83.         @Override
  84.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  85.             return new Rotation(pv.getPosition(), pv.getMomentum(),
  86.                                 Vector3D.PLUS_I, Vector3D.PLUS_K);
  87.         }

  88.         /** {@inheritDoc} */
  89.         @Override
  90.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  91.                                                                                          final FieldPVCoordinates<T> pv) {
  92.             return new FieldRotation<>(pv.getPosition(), pv.getMomentum(),
  93.                                        new FieldVector3D<>(field, Vector3D.PLUS_I),
  94.                                        new FieldVector3D<>(field, Vector3D.PLUS_K));
  95.         }

  96.     },

  97.     /** Constant for Local Vertical, Local Horizontal frame
  98.      * (X axis aligned with position, Z axis aligned with orbital momentum).
  99.      * <p>
  100.      * BEWARE! Depending on the background (software used, textbook, community),
  101.      * different incompatible definitions for LVLH are used. This one is consistent
  102.      * with Vallado's book and with AGI's STK. However CCSDS standard, Wertz, and
  103.      * a.i. solutions' FreeFlyer use another definition (see {@link #LVLH_CCSDS}).
  104.      * </p>
  105.      * <p>
  106.      * This frame is also known as the {@link #QSW} frame, both constants are equivalent.
  107.      * </p>
  108.      * <p>
  109.      * The axes of these frames are parallel to the axes of the {@link #LVLH_CCSDS} frame:
  110.      * <ul>
  111.      *   <li>X<sub>LVLH/QSW</sub> = -Z<sub>LVLH_CCSDS</sub></li>
  112.      *   <li>Y<sub>LVLH/QSW</sub> =  X<sub>LVLH_CCSDS</sub></li>
  113.      *   <li>Z<sub>LVLH/QSW</sub> = -Y<sub>LVLH_CCSDS</sub></li>
  114.      * </ul>
  115.      *
  116.      * @see #QSW
  117.      * @see #VVLH
  118.      */
  119.     LVLH {
  120.         /** {@inheritDoc} */
  121.         @Override
  122.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  123.             return new Rotation(pv.getPosition(), pv.getMomentum(),
  124.                                 Vector3D.PLUS_I, Vector3D.PLUS_K);
  125.         }

  126.         /** {@inheritDoc} */
  127.         @Override
  128.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  129.                                                                                          final FieldPVCoordinates<T> pv) {
  130.             return new FieldRotation<>(pv.getPosition(), pv.getMomentum(),
  131.                                        new FieldVector3D<>(field, Vector3D.PLUS_I),
  132.                                        new FieldVector3D<>(field, Vector3D.PLUS_K));
  133.         }

  134.     },

  135.     /** Constant for Local Vertical, Local Horizontal frame as defined by CCSDS
  136.      * (Z axis aligned with opposite of position, Y axis aligned with opposite of orbital momentum).
  137.      * <p>
  138.      * BEWARE! Depending on the background (software used, textbook, community),
  139.      * different incompatible definitions for LVLH are used. This one is consistent
  140.      * with CCSDS standard, Wertz, and a.i. solutions' FreeFlyer. However Vallado's
  141.      * book and with AGI's STK use another definition (see {@link #LVLH}).
  142.      * </p>
  143.      * <p>
  144.      * The axes of this frame are parallel to the axes of both the {@link #QSW} and {@link #LVLH} frames:
  145.      * <ul>
  146.      *   <li>X<sub>LVLH_CCSDS/VVLH</sub> =  Y<sub>QSW/LVLH</sub></li>
  147.      *   <li>Y<sub>LVLH_CCSDS/VVLH</sub> = -Z<sub>QSW/LVLH</sub></li>
  148.      *   <li>Z<sub>LVLH_CCSDS/VVLH</sub> = -X<sub>QSW/LVLH</sub></li>
  149.      * </ul>
  150.      *
  151.      * @see #QSW
  152.      * @see #LVLH
  153.      * @since 11.0
  154.      */
  155.     LVLH_CCSDS {
  156.         /** {@inheritDoc} */
  157.         @Override
  158.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  159.             return new Rotation(pv.getPosition(), pv.getMomentum(),
  160.                                 Vector3D.MINUS_K, Vector3D.MINUS_J);
  161.         }

  162.         /** {@inheritDoc} */
  163.         @Override
  164.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  165.                                                                                          final FieldPVCoordinates<T> pv) {
  166.             return new FieldRotation<>(pv.getPosition(), pv.getMomentum(),
  167.                                        new FieldVector3D<>(field, Vector3D.MINUS_K),
  168.                                        new FieldVector3D<>(field, Vector3D.MINUS_J));
  169.         }

  170.     },

  171.     /** Constant for Vehicle Velocity, Local Horizontal frame
  172.      * (Z axis aligned with opposite of position, Y axis aligned with opposite of orbital momentum).
  173.      * <p>
  174.      * This is another name for {@link #LVLH_CCSDS}, kept here for compatibility with STK.
  175.      * </p>
  176.      * <p>
  177.      * Beware that the name is misleading: in the general case (i.e. not perfectly circular),
  178.      * none of the axes is perfectly aligned with velocity! The preferred name for this
  179.      * should be {@link #LVLH_CCSDS}.
  180.      * </p>
  181.      * <p>
  182.      * The axes of this frame are parallel to the axes of both the {@link #QSW} and {@link #LVLH} frames:
  183.      * <ul>
  184.      *   <li>X<sub>LVLH_CCSDS/VVLH</sub> =  Y<sub>QSW/LVLH</sub></li>
  185.      *   <li>Y<sub>LVLH_CCSDS/VVLH</sub> = -Z<sub>QSW/LVLH</sub></li>
  186.      *   <li>Z<sub>LVLH_CCSDS/VVLH</sub> = -X<sub>QSW/LVLH</sub></li>
  187.      * </ul>
  188.      * @see #LVLH_CCSDS
  189.      */
  190.     VVLH {
  191.         /** {@inheritDoc} */
  192.         @Override
  193.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  194.             return LVLH_CCSDS.rotationFromInertial(pv);
  195.         }

  196.         /** {@inheritDoc} */
  197.         @Override
  198.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  199.                                                                                          final FieldPVCoordinates<T> pv) {
  200.             return LVLH_CCSDS.rotationFromInertial(field, pv);
  201.         }

  202.     },

  203.     /** Constant for Velocity - Normal - Co-normal frame
  204.      * (X axis aligned with velocity, Y axis aligned with orbital momentum).
  205.      * <p>
  206.      * The axes of this frame are parallel to the axes of the {@link #TNW}
  207.      * and {@link #NTW} frames:
  208.      * <ul>
  209.      *   <li>X<sub>VNC</sub> =  X<sub>TNW</sub> = Y<sub>NTW</sub></li>
  210.      *   <li>Y<sub>VNC</sub> =  Z<sub>TNW</sub> = Z<sub>NTW</sub></li>
  211.      *   <li>Z<sub>VNC</sub> = -Y<sub>TNW</sub> = X<sub>NTW</sub></li>
  212.      * </ul>
  213.      *
  214.      * @see #TNW
  215.      * @see #NTW
  216.      */
  217.     VNC {
  218.         /** {@inheritDoc} */
  219.         @Override
  220.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  221.             return new Rotation(pv.getVelocity(), pv.getMomentum(),
  222.                                 Vector3D.PLUS_I, Vector3D.PLUS_J);
  223.         }

  224.         /** {@inheritDoc} */
  225.         @Override
  226.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  227.                                                                                          final FieldPVCoordinates<T> pv) {
  228.             return new FieldRotation<>(pv.getVelocity(), pv.getMomentum(),
  229.                                        new FieldVector3D<>(field, Vector3D.PLUS_I),
  230.                                        new FieldVector3D<>(field, Vector3D.PLUS_J));
  231.         }

  232.     },

  233.     /** Constant for Equinoctial Coordinate System
  234.      * (X axis aligned with ascending node, Z axis aligned with orbital momentum).
  235.      * @since 11.0
  236.      */
  237.     EQW {
  238.         /** {@inheritDoc} */
  239.         @Override
  240.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  241.             final Vector3D m = pv.getMomentum();
  242.             return new Rotation(new Vector3D(-m.getY(), m.getX(), 0), m,
  243.                                 Vector3D.PLUS_I, Vector3D.PLUS_J);
  244.         }

  245.         /** {@inheritDoc} */
  246.         @Override
  247.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  248.                                                                                          final FieldPVCoordinates<T> pv) {
  249.             final FieldVector3D<T> m = pv.getMomentum();
  250.             return new FieldRotation<>(new FieldVector3D<>(m.getY().negate(), m.getX(), field.getZero()),
  251.                                        m,
  252.                                        new FieldVector3D<>(field, Vector3D.PLUS_I),
  253.                                        new FieldVector3D<>(field, Vector3D.PLUS_J));
  254.         }

  255.     },

  256.     /** Constant for Transverse Velocity Normal coordinate system
  257.      * (Y axis aligned with velocity, Z axis aligned with orbital momentum).
  258.      * <p>
  259.      * The axes of this frame are parallel to the axes of the {@link #TNW}
  260.      * and {@link #VNC} frames:
  261.      * <ul>
  262.      *   <li>X<sub>NTW</sub> = -Y<sub>TNW</sub> = Z<sub>VNC</sub></li>
  263.      *   <li>Y<sub>NTW</sub> =  X<sub>TNW</sub> = X<sub>VNC</sub></li>
  264.      *   <li>Z<sub>NTW</sub> =  Z<sub>TNW</sub> = Y<sub>VNC</sub></li>
  265.      * </ul>
  266.      * @see #TNW
  267.      * @see #VNC
  268.      * @since 11.0
  269.      */
  270.     NTW {
  271.         /** {@inheritDoc} */
  272.         @Override
  273.         public Rotation rotationFromInertial(final PVCoordinates pv) {
  274.             return new Rotation(pv.getVelocity(), pv.getMomentum(),
  275.                                 Vector3D.PLUS_J, Vector3D.PLUS_K);
  276.         }

  277.         /** {@inheritDoc} */
  278.         @Override
  279.         public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
  280.                                                                                          final FieldPVCoordinates<T> pv) {
  281.             return new FieldRotation<>(pv.getVelocity(), pv.getMomentum(),
  282.                                        new FieldVector3D<>(field, Vector3D.PLUS_J),
  283.                                        new FieldVector3D<>(field, Vector3D.PLUS_K));
  284.         }

  285.     };

  286.     /**
  287.      * Get the rotation from input to output {@link LOFType commonly used local orbital frame}.
  288.      * <p>
  289.      * This rotation does not include any time derivatives.
  290.      * </p>
  291.      *
  292.      * @param in input commonly used local orbital frame
  293.      * @param out output commonly used local orbital frame
  294.      * @param pv position-velocity of the spacecraft in some inertial frame
  295.      * @return rotation from input to output {@link LOFType commonly used local orbital frame}.
  296.      * @since 11.3
  297.      */
  298.     public static Rotation rotationFromLOFInToLOFOut(final LOFType in, final LOFType out, final PVCoordinates pv) {
  299.         return out.rotationFromLOFType(in, pv);
  300.     }

  301.     /**
  302.      * Get the rotation from input to output {@link LOFType commonly used local orbital frame}.
  303.      * <p>
  304.      * This rotation does not include any time derivatives.
  305.      * </p>
  306.      *
  307.      * @param field field to which the elements belong
  308.      * @param in input commonly used local orbital frame
  309.      * @param out output commonly used local orbital frame
  310.      * @param pv position-velocity of the spacecraft in some inertial frame
  311.      * @param <T> type of the field elements
  312.      * @return rotation from input to output {@link LOFType commonly used local orbital frame}.
  313.      * @since 11.3
  314.      */
  315.     public static <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromLOFInToLOFOut(final Field<T> field,
  316.                                                                                                  final LOFType in,
  317.                                                                                                  final LOFType out,
  318.                                                                                                  final FieldPVCoordinates<T> pv) {
  319.         return out.rotationFromLOFType(field, in, pv);
  320.     }

  321.     /**
  322.      * Get the transform from input to output {@link LOFType commonly used local orbital frame}.
  323.      * <p>
  324.      * This method simply builds the transform using the rotation obtained from
  325.      * {@link LOFType#rotationFromLOFInToLOFOut(LOFType, LOFType, PVCoordinates)}
  326.      * </p>
  327.      *
  328.      * @param in input commonly used local orbital frame
  329.      * @param out output commonly used local orbital frame
  330.      * @param date current date
  331.      * @param pv position-velocity of the spacecraft in some inertial frame
  332.      * @return rotation from input to output {@link LOFType commonly used local orbital frame}.
  333.      * @since 11.3
  334.      */
  335.     public static Transform transformFromLOFInToLOFOut(final LOFType in, final LOFType out, final AbsoluteDate date,
  336.                                                       final PVCoordinates pv) {
  337.         return new Transform(date, rotationFromLOFInToLOFOut(in, out, pv));
  338.     }

  339.     /**
  340.      * Get the transform from input to output {@link LOFType commonly used local orbital frame}.
  341.      * <p>
  342.      * This method simply builds the transform using the rotation obtained from
  343.      * {@link LOFType#rotationFromLOFInToLOFOut(LOFType, LOFType, PVCoordinates)}
  344.      * </p>
  345.      *
  346.      * @param field field to which the elements belong
  347.      * @param in input commonly used local orbital frame
  348.      * @param out output commonly used local orbital frame
  349.      * @param date current date
  350.      * @param pv position-velocity of the spacecraft in some inertial frame
  351.      * @param <T> type of the field elements
  352.      * @return rotation from input to output {@link LOFType commonly used local orbital frame}.
  353.      * @since 11.3
  354.      */
  355.     public static <T extends CalculusFieldElement<T>> FieldTransform<T> transformFromLOFInToLOFOut(final Field<T> field,
  356.                                                                                                    final LOFType in,
  357.                                                                                                    final LOFType out,
  358.                                                                                                    final FieldAbsoluteDate<T> date,
  359.                                                                                                    final FieldPVCoordinates<T> pv) {
  360.         return new FieldTransform<T>(date, rotationFromLOFInToLOFOut(field, in, out, pv));
  361.     }

  362.     /**
  363.      * Get the rotation from input {@link LOFType commonly used local orbital frame} to the instance.
  364.      * @param fromLOF input local orbital frame
  365.      * @param pv position-velocity of the spacecraft in some inertial frame
  366.      * @return rotation from input local orbital frame to the instance
  367.      * @since 11.3
  368.      */
  369.     public Rotation rotationFromLOFType(final LOFType fromLOF, final PVCoordinates pv) {

  370.         // First compute the rotation from the input LOF to the pivot inertial
  371.         final Rotation fromLOFToInertial = fromLOF.rotationFromInertial(pv).revert();

  372.         // Then compute the rotation from the pivot inertial to the output LOF
  373.         final Rotation inertialToThis = this.rotationFromInertial(pv);

  374.         // Output composed rotation
  375.         return fromLOFToInertial.compose(inertialToThis, RotationConvention.FRAME_TRANSFORM);
  376.     }

  377.     /**
  378.      * Get the rotation from input {@link LOFType commonly used local orbital frame} to the instance.
  379.      * @param field field to which the elements belong
  380.      * @param fromLOF input local orbital frame
  381.      * @param pv position-velocity of the spacecraft in some inertial frame
  382.      * @param <T> type of the field elements
  383.      * @return rotation from input local orbital frame to the instance
  384.      * @since 11.3
  385.      */
  386.     public <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromLOFType(final Field<T> field,
  387.                                                                                     final LOFType fromLOF,
  388.                                                                                     final FieldPVCoordinates<T> pv) {

  389.         // First compute the rotation from the input LOF to the pivot inertial
  390.         final FieldRotation<T> fromLOFToInertial = fromLOF.rotationFromInertial(field, pv).revert();

  391.         // Then compute the rotation from the pivot inertial to the output LOF
  392.         final FieldRotation<T> inertialToThis = this.rotationFromInertial(field, pv);

  393.         // Output composed rotation
  394.         return fromLOFToInertial.compose(inertialToThis, RotationConvention.FRAME_TRANSFORM);
  395.     }

  396.     /**
  397.      * Get the transform from an inertial frame defining position-velocity and the local orbital frame.
  398.      *
  399.      * @param date current date
  400.      * @param pv   position-velocity of the spacecraft in some inertial frame
  401.      * @return transform from the frame where position-velocity are defined to local orbital frame
  402.      */
  403.     public Transform transformFromInertial(final AbsoluteDate date, final PVCoordinates pv) {

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

  406.         // compute the rotation part of the transform
  407.         final Rotation r        = rotationFromInertial(pv);
  408.         final Vector3D p        = pv.getPosition();
  409.         final Vector3D momentum = pv.getMomentum();
  410.         final Transform rotation =
  411.                 new Transform(date, r, new Vector3D(1.0 / p.getNormSq(), r.applyTo(momentum)));

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

  413.     }

  414.     /**
  415.      * Get the transform from an inertial frame defining position-velocity and the local orbital frame.
  416.      *
  417.      * @param date current date
  418.      * @param pv   position-velocity of the spacecraft in some inertial frame
  419.      * @param <T>  type of the fields elements
  420.      * @return transform from the frame where position-velocity are defined to local orbital frame
  421.      * @since 9.0
  422.      */
  423.     public <T extends CalculusFieldElement<T>> FieldTransform<T> transformFromInertial(final FieldAbsoluteDate<T> date,
  424.                                                                                        final FieldPVCoordinates<T> pv) {

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

  427.         // compute the rotation part of the transform
  428.         final FieldRotation<T> r        = rotationFromInertial(date.getField(), pv);
  429.         final FieldVector3D<T> p        = pv.getPosition();
  430.         final FieldVector3D<T> momentum = pv.getMomentum();
  431.         final FieldTransform<T> rotation =
  432.                 new FieldTransform<T>(date, r, new FieldVector3D<>(p.getNormSq().reciprocal(), r.applyTo(momentum)));

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

  434.     }

  435.     /**
  436.      * Get the rotation from inertial frame to local orbital frame.
  437.      * <p>
  438.      * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as
  439.      * well, the full {@link #transformFromInertial(AbsoluteDate, PVCoordinates) transformFromInertial} method must be
  440.      * called and the complete rotation transform must be extracted from it.
  441.      * </p>
  442.      *
  443.      * @param pv position-velocity of the spacecraft in some inertial frame
  444.      * @return rotation from inertial frame to local orbital frame
  445.      */
  446.     public abstract Rotation rotationFromInertial(PVCoordinates pv);

  447.     /** Get the rotation from inertial frame to local orbital frame.
  448.      * <p>
  449.      * This rotation does not include any time derivatives. If first
  450.      * time derivatives (i.e. rotation rate) is needed as well, the full
  451.      * {@link #transformFromInertial(FieldAbsoluteDate, FieldPVCoordinates) transformFromInertial}
  452.      * method must be called and the complete rotation transform must be extracted
  453.      * from it.
  454.      * </p>
  455.      * @param field field to which the elements belong
  456.      * @param pv position-velocity of the spacecraft in some inertial frame
  457.      * @param <T> type of the field elements
  458.      * @return rotation from inertial frame to local orbital frame
  459.      * @since 9.0
  460.      */
  461.     public abstract <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(Field<T> field,
  462.                                                                                           FieldPVCoordinates<T> pv);

  463. }