OrbitType.java

  1. /* Copyright 2002-2025 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.orbits;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.Field;
  20. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  21. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  22. import org.hipparchus.util.FastMath;
  23. import org.hipparchus.util.MathUtils;
  24. import org.orekit.errors.OrekitException;
  25. import org.orekit.errors.OrekitMessages;
  26. import org.orekit.frames.Frame;
  27. import org.orekit.time.AbsoluteDate;
  28. import org.orekit.time.FieldAbsoluteDate;
  29. import org.orekit.utils.FieldPVCoordinates;
  30. import org.orekit.utils.PVCoordinates;
  31. import org.orekit.utils.ParameterDriver;
  32. import org.orekit.utils.ParameterDriversList;
  33. import org.orekit.utils.TimeStampedFieldPVCoordinates;

  34. /** Enumerate for {@link Orbit} and {@link FieldOrbit} parameters types.
  35.  */
  36. public enum OrbitType {

  37.     /** Type for orbital representation in {@link CartesianOrbit} and {@link FieldCartesianOrbit} parameters. */
  38.     CARTESIAN {

  39.         /** {@inheritDoc} */
  40.         @Override
  41.         public CartesianOrbit convertType(final Orbit orbit) {
  42.             return (orbit.getType() == this) ? (CartesianOrbit) orbit : new CartesianOrbit(orbit);
  43.         }

  44.         /** {@inheritDoc} */
  45.         @Override
  46.         public void mapOrbitToArray(final Orbit orbit, final PositionAngleType type,
  47.                                     final double[] stateVector, final double[] stateVectorDot) {

  48.             final PVCoordinates pv = orbit.getPVCoordinates();
  49.             final Vector3D      p  = pv.getPosition();
  50.             final Vector3D      v  = pv.getVelocity();

  51.             stateVector[0] = p.getX();
  52.             stateVector[1] = p.getY();
  53.             stateVector[2] = p.getZ();
  54.             stateVector[3] = v.getX();
  55.             stateVector[4] = v.getY();
  56.             stateVector[5] = v.getZ();

  57.             if (stateVectorDot != null) {
  58.                 final Vector3D a  = pv.getAcceleration();
  59.                 stateVectorDot[0] = v.getX();
  60.                 stateVectorDot[1] = v.getY();
  61.                 stateVectorDot[2] = v.getZ();
  62.                 stateVectorDot[3] = a.getX();
  63.                 stateVectorDot[4] = a.getY();
  64.                 stateVectorDot[5] = a.getZ();
  65.             }

  66.         }

  67.         /** {@inheritDoc} */
  68.         @Override
  69.         public CartesianOrbit mapArrayToOrbit(final double[] stateVector, final double[] stateVectorDot, final PositionAngleType type,
  70.                                               final AbsoluteDate date, final double mu, final Frame frame) {

  71.             final Vector3D p = new Vector3D(stateVector[0], stateVector[1], stateVector[2]);
  72.             final Vector3D v = new Vector3D(stateVector[3], stateVector[4], stateVector[5]);
  73.             final Vector3D a;
  74.             if (stateVectorDot == null) {
  75.                 // we don't have data about acceleration
  76.                 return new CartesianOrbit(new PVCoordinates(p, v), frame, date, mu);
  77.             } else {
  78.                 // we do have an acceleration
  79.                 a = new Vector3D(stateVectorDot[3], stateVectorDot[4], stateVectorDot[5]);
  80.                 return new CartesianOrbit(new PVCoordinates(p, v, a), frame, date, mu);
  81.             }

  82.         }

  83.         /** {@inheritDoc} */
  84.         @Override
  85.         public <T extends CalculusFieldElement<T>> FieldCartesianOrbit<T> convertType(final FieldOrbit<T> orbit) {
  86.             return (orbit.getType() == this) ? (FieldCartesianOrbit<T>) orbit : new FieldCartesianOrbit<>(orbit);
  87.         }

  88.         /** {@inheritDoc} */
  89.         @Override
  90.         public <T extends CalculusFieldElement<T>> void mapOrbitToArray(final FieldOrbit<T> orbit,
  91.                                                                         final PositionAngleType type,
  92.                                                                         final T[] stateVector,
  93.                                                                         final T[] stateVectorDot) {

  94.             final TimeStampedFieldPVCoordinates<T> pv = orbit.getPVCoordinates();
  95.             final FieldVector3D<T>                 p  = pv.getPosition();
  96.             final FieldVector3D<T>                 v  = pv.getVelocity();

  97.             stateVector[0] = p.getX();
  98.             stateVector[1] = p.getY();
  99.             stateVector[2] = p.getZ();
  100.             stateVector[3] = v.getX();
  101.             stateVector[4] = v.getY();
  102.             stateVector[5] = v.getZ();

  103.             if (stateVectorDot != null) {
  104.                 final FieldVector3D<T> a = pv.getAcceleration();
  105.                 stateVectorDot[0] = v.getX();
  106.                 stateVectorDot[1] = v.getY();
  107.                 stateVectorDot[2] = v.getZ();
  108.                 stateVectorDot[3] = a.getX();
  109.                 stateVectorDot[4] = a.getY();
  110.                 stateVectorDot[5] = a.getZ();
  111.             }

  112.         }

  113.         /** {@inheritDoc} */
  114.         @Override
  115.         public <T extends CalculusFieldElement<T>> FieldCartesianOrbit<T> mapArrayToOrbit(final T[] stateVector,
  116.                                                                                           final T[] stateVectorDot,
  117.                                                                                           final PositionAngleType type,
  118.                                                                                           final FieldAbsoluteDate<T> date,
  119.                                                                                           final T mu, final Frame frame) {
  120.             final FieldVector3D<T> p = new FieldVector3D<>(stateVector[0], stateVector[1], stateVector[2]);
  121.             final FieldVector3D<T> v = new FieldVector3D<>(stateVector[3], stateVector[4], stateVector[5]);
  122.             final FieldVector3D<T> a;
  123.             if (stateVectorDot == null) {
  124.                 // we don't have data about acceleration
  125.                 return new FieldCartesianOrbit<>(new FieldPVCoordinates<>(p, v), frame, date, mu);
  126.             } else {
  127.                 // we do have an acceleration
  128.                 a = new FieldVector3D<>(stateVectorDot[3], stateVectorDot[4], stateVectorDot[5]);
  129.                 return new FieldCartesianOrbit<>(new FieldPVCoordinates<>(p, v, a), frame, date, mu);
  130.             }

  131.         }

  132.         /** {@inheritDoc} */
  133.         @Override
  134.         public <T extends CalculusFieldElement<T>> FieldCartesianOrbit<T> convertToFieldOrbit(final Field<T> field,
  135.                                                                                               final Orbit orbit) {
  136.             return new FieldCartesianOrbit<>(field, CARTESIAN.convertType(orbit));
  137.         }

  138.         /** {@inheritDoc} */
  139.         @Override
  140.         public ParameterDriversList getDrivers(final double dP, final Orbit orbit, final PositionAngleType type) {
  141.             final ParameterDriversList drivers = new ParameterDriversList();
  142.             final double[] array = new double[6];
  143.             mapOrbitToArray(orbit, type, array, null);
  144.             final double[] scale = scale(dP, orbit);
  145.             drivers.add(new ParameterDriver(POS_X, array[0], scale[0], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  146.             drivers.add(new ParameterDriver(POS_Y, array[1], scale[1], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  147.             drivers.add(new ParameterDriver(POS_Z, array[2], scale[2], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  148.             drivers.add(new ParameterDriver(VEL_X, array[3], scale[3], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  149.             drivers.add(new ParameterDriver(VEL_Y, array[4], scale[4], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  150.             drivers.add(new ParameterDriver(VEL_Z, array[5], scale[5], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  151.             return drivers;
  152.         }

  153.         /** {@inheritDoc} */
  154.         @Override
  155.         public CartesianOrbit normalize(final Orbit orbit, final Orbit reference) {
  156.             // no angular parameters need normalization
  157.             return convertType(orbit);
  158.         }

  159.         /** {@inheritDoc} */
  160.         @Override
  161.         public <T extends CalculusFieldElement<T>> FieldCartesianOrbit<T> normalize(final FieldOrbit<T> orbit, final FieldOrbit<T> reference) {
  162.             // no angular parameters need normalization
  163.             return convertType(orbit);
  164.         }

  165.         /** {@inheritDoc} */
  166.         @Override
  167.         public boolean isPositionAngleBased() {
  168.             return false;
  169.         }

  170.     },

  171.     /** Type for orbital representation in {@link CircularOrbit} and {@link FieldCircularOrbit} parameters. */
  172.     CIRCULAR {

  173.         /** {@inheritDoc} */
  174.         @Override
  175.         public CircularOrbit convertType(final Orbit orbit) {
  176.             return (orbit.getType() == this) ? (CircularOrbit) orbit : new CircularOrbit(orbit);
  177.         }

  178.         /** {@inheritDoc} */
  179.         @Override
  180.         public void mapOrbitToArray(final Orbit orbit, final PositionAngleType type,
  181.                                     final double[] stateVector, final double[] stateVectorDot) {

  182.             final CircularOrbit circularOrbit = (CircularOrbit) OrbitType.CIRCULAR.convertType(orbit);

  183.             stateVector[0] = circularOrbit.getA();
  184.             stateVector[1] = circularOrbit.getCircularEx();
  185.             stateVector[2] = circularOrbit.getCircularEy();
  186.             stateVector[3] = circularOrbit.getI();
  187.             stateVector[4] = circularOrbit.getRightAscensionOfAscendingNode();
  188.             stateVector[5] = circularOrbit.getAlpha(type);

  189.             if (stateVectorDot != null) {
  190.                 stateVectorDot[0] = circularOrbit.getADot();
  191.                 stateVectorDot[1] = circularOrbit.getCircularExDot();
  192.                 stateVectorDot[2] = circularOrbit.getCircularEyDot();
  193.                 stateVectorDot[3] = circularOrbit.getIDot();
  194.                 stateVectorDot[4] = circularOrbit.getRightAscensionOfAscendingNodeDot();
  195.                 stateVectorDot[5] = circularOrbit.getAlphaDot(type);
  196.             }

  197.         }

  198.         /** {@inheritDoc} */
  199.         @Override
  200.         public CircularOrbit mapArrayToOrbit(final double[] stateVector, final double[] stateVectorDot, final PositionAngleType type,
  201.                                              final AbsoluteDate date, final double mu, final Frame frame) {
  202.             if (stateVectorDot == null) {
  203.                 // we don't have orbit derivatives
  204.                 return new CircularOrbit(stateVector[0], stateVector[1], stateVector[2],
  205.                                          stateVector[3], stateVector[4], stateVector[5],
  206.                                          type, frame, date, mu);
  207.             } else {
  208.                 // we have orbit derivatives
  209.                 return new CircularOrbit(stateVector[0],    stateVector[1],    stateVector[2],
  210.                                          stateVector[3],    stateVector[4],    stateVector[5],
  211.                                          stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  212.                                          stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  213.                                          type, frame, date, mu);
  214.             }
  215.         }

  216.         /** {@inheritDoc} */
  217.         @Override
  218.         public <T extends CalculusFieldElement<T>> FieldCircularOrbit<T> convertType(final FieldOrbit<T> orbit) {
  219.             return (orbit.getType() == this) ? (FieldCircularOrbit<T>) orbit : new FieldCircularOrbit<>(orbit);
  220.         }

  221.         /** {@inheritDoc} */
  222.         @Override
  223.         public <T extends CalculusFieldElement<T>> void mapOrbitToArray(final FieldOrbit<T> orbit,
  224.                                                                         final PositionAngleType type,
  225.                                                                         final T[] stateVector,
  226.                                                                         final T[] stateVectorDot) {

  227.             final FieldCircularOrbit<T> circularOrbit = (FieldCircularOrbit<T>) OrbitType.CIRCULAR.convertType(orbit);

  228.             stateVector[0] = circularOrbit.getA();
  229.             stateVector[1] = circularOrbit.getCircularEx();
  230.             stateVector[2] = circularOrbit.getCircularEy();
  231.             stateVector[3] = circularOrbit.getI();
  232.             stateVector[4] = circularOrbit.getRightAscensionOfAscendingNode();
  233.             stateVector[5] = circularOrbit.getAlpha(type);

  234.             if (stateVectorDot != null) {
  235.                 stateVectorDot[0] = circularOrbit.getADot();
  236.                 stateVectorDot[1] = circularOrbit.getCircularExDot();
  237.                 stateVectorDot[2] = circularOrbit.getCircularEyDot();
  238.                 stateVectorDot[3] = circularOrbit.getIDot();
  239.                 stateVectorDot[4] = circularOrbit.getRightAscensionOfAscendingNodeDot();
  240.                 stateVectorDot[5] = circularOrbit.getAlphaDot(type);
  241.             }

  242.         }

  243.         /** {@inheritDoc} */
  244.         @Override
  245.         public <T extends CalculusFieldElement<T>> FieldCircularOrbit<T> mapArrayToOrbit(final T[] stateVector,
  246.                                                                                          final T[] stateVectorDot, final PositionAngleType type,
  247.                                                                                          final FieldAbsoluteDate<T> date,
  248.                                                                                          final T mu, final Frame frame) {
  249.             if (stateVectorDot == null) {
  250.                 // we don't have orbit derivatives
  251.                 return new FieldCircularOrbit<>(stateVector[0], stateVector[1], stateVector[2],
  252.                                                 stateVector[3], stateVector[4], stateVector[5],
  253.                                                 type, frame, date, mu);
  254.             } else {
  255.                 // we have orbit derivatives
  256.                 return new FieldCircularOrbit<>(stateVector[0],    stateVector[1],    stateVector[2],
  257.                                                 stateVector[3],    stateVector[4],    stateVector[5],
  258.                                                 stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  259.                                                 stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  260.                                                 type, frame, date, mu);
  261.             }
  262.         }

  263.         /** {@inheritDoc} */
  264.         @Override
  265.         public <T extends CalculusFieldElement<T>> FieldCircularOrbit<T> convertToFieldOrbit(final Field<T> field,
  266.                                                                                              final Orbit orbit) {
  267.             return new FieldCircularOrbit<>(field, CIRCULAR.convertType(orbit));
  268.         }

  269.         /** {@inheritDoc} */
  270.         @Override
  271.         public ParameterDriversList getDrivers(final double dP, final Orbit orbit, final PositionAngleType type) {
  272.             final ParameterDriversList drivers = new ParameterDriversList();
  273.             final double[] array = new double[6];
  274.             mapOrbitToArray(orbit, type, array, null);
  275.             final double[] scale = scale(dP, orbit);
  276.             final String name = type == PositionAngleType.MEAN ?
  277.                                     MEAN_LAT_ARG :
  278.                                     type == PositionAngleType.ECCENTRIC ? ECC_LAT_ARG : TRUE_LAT_ARG;
  279.             drivers.add(new ParameterDriver(A,    array[0], scale[0],  0.0, Double.POSITIVE_INFINITY));
  280.             drivers.add(new ParameterDriver(E_X,  array[1], scale[1], -1.0, 1.0));
  281.             drivers.add(new ParameterDriver(E_Y,  array[2], scale[2], -1.0, 1.0));
  282.             drivers.add(new ParameterDriver(INC,  array[3], scale[3],  0.0, FastMath.PI));
  283.             drivers.add(new ParameterDriver(RAAN, array[4], scale[4], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  284.             drivers.add(new ParameterDriver(name, array[5], scale[5], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  285.             return drivers;
  286.         }

  287.         /** {@inheritDoc} */
  288.         @Override
  289.         public CircularOrbit normalize(final Orbit orbit, final Orbit reference) {

  290.             // convert input to proper type
  291.             final CircularOrbit cO = convertType(orbit);
  292.             final CircularOrbit cR = convertType(reference);
  293.             final PositionAngleType cachedPositionAngleType = cO.getCachedPositionAngleType();

  294.             // perform normalization
  295.             return new CircularOrbit(cO.getA(),
  296.                                      cO.getCircularEx(),
  297.                                      cO.getCircularEy(),
  298.                                      cO.getI(),
  299.                                      MathUtils.normalizeAngle(cO.getRightAscensionOfAscendingNode(),
  300.                                              cR.getRightAscensionOfAscendingNode()),
  301.                                      MathUtils.normalizeAngle(cO.getAlpha(cachedPositionAngleType),
  302.                                              cR.getAlpha(cachedPositionAngleType)),
  303.                                      cO.getADot(),
  304.                                      cO.getCircularExDot(),
  305.                                      cO.getCircularEyDot(),
  306.                                      cO.getIDot(),
  307.                                      cO.getRightAscensionOfAscendingNodeDot(),
  308.                                      cO.getAlphaDot(cachedPositionAngleType),
  309.                                      cachedPositionAngleType,
  310.                                      cO.getFrame(),
  311.                                      cO.getDate(),
  312.                                      cO.getMu());

  313.         }

  314.         /** {@inheritDoc} */
  315.         @Override
  316.         public <T extends CalculusFieldElement<T>> FieldCircularOrbit<T> normalize(final FieldOrbit<T> orbit, final FieldOrbit<T> reference) {

  317.             // convert input to proper type
  318.             final FieldCircularOrbit<T> cO = convertType(orbit);
  319.             final FieldCircularOrbit<T> cR = convertType(reference);
  320.             final PositionAngleType positionAngleType = cO.getCachedPositionAngleType();

  321.             // perform normalization
  322.             if (cO.hasNonKeplerianAcceleration()) {
  323.                 return new FieldCircularOrbit<>(cO.getA(),
  324.                                                 cO.getCircularEx(),
  325.                                                 cO.getCircularEy(),
  326.                                                 cO.getI(),
  327.                                                 MathUtils.normalizeAngle(cO.getRightAscensionOfAscendingNode(),
  328.                                                         cR.getRightAscensionOfAscendingNode()),
  329.                                                 MathUtils.normalizeAngle(cO.getAlpha(positionAngleType),
  330.                                                         cR.getAlpha(positionAngleType)),
  331.                                                 cO.getADot(),
  332.                                                 cO.getCircularExDot(),
  333.                                                 cO.getCircularEyDot(),
  334.                                                 cO.getIDot(),
  335.                                                 cO.getRightAscensionOfAscendingNodeDot(),
  336.                                                 cO.getAlphaDot(positionAngleType),
  337.                                                 positionAngleType,
  338.                                                 cO.getFrame(),
  339.                                                 cO.getDate(),
  340.                                                 cO.getMu());
  341.             } else {
  342.                 return new FieldCircularOrbit<>(cO.getA(),
  343.                                                 cO.getCircularEx(),
  344.                                                 cO.getCircularEy(),
  345.                                                 cO.getI(),
  346.                                                 MathUtils.normalizeAngle(cO.getRightAscensionOfAscendingNode(),
  347.                                                         cR.getRightAscensionOfAscendingNode()),
  348.                                                 MathUtils.normalizeAngle(cO.getAlpha(positionAngleType),
  349.                                                         cR.getAlpha(positionAngleType)),
  350.                                                 positionAngleType,
  351.                                                 cO.getFrame(),
  352.                                                 cO.getDate(),
  353.                                                 cO.getMu());
  354.             }

  355.         }

  356.         /** {@inheritDoc} */
  357.         @Override
  358.         public boolean isPositionAngleBased() {
  359.             return true;
  360.         }

  361.     },

  362.     /** Type for orbital representation in {@link EquinoctialOrbit} and {@link FieldEquinoctialOrbit} parameters. */
  363.     EQUINOCTIAL {

  364.         /** {@inheritDoc} */
  365.         @Override
  366.         public EquinoctialOrbit convertType(final Orbit orbit) {
  367.             return (orbit.getType() == this) ? (EquinoctialOrbit) orbit : new EquinoctialOrbit(orbit);
  368.         }

  369.         /** {@inheritDoc} */
  370.         @Override
  371.         public void mapOrbitToArray(final Orbit orbit, final PositionAngleType type,
  372.                                     final double[] stateVector, final double[] stateVectorDot) {

  373.             final EquinoctialOrbit equinoctialOrbit =
  374.                 (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(orbit);

  375.             stateVector[0] = equinoctialOrbit.getA();
  376.             stateVector[1] = equinoctialOrbit.getEquinoctialEx();
  377.             stateVector[2] = equinoctialOrbit.getEquinoctialEy();
  378.             stateVector[3] = equinoctialOrbit.getHx();
  379.             stateVector[4] = equinoctialOrbit.getHy();
  380.             stateVector[5] = equinoctialOrbit.getL(type);

  381.             if (stateVectorDot != null) {
  382.                 stateVectorDot[0] = equinoctialOrbit.getADot();
  383.                 stateVectorDot[1] = equinoctialOrbit.getEquinoctialExDot();
  384.                 stateVectorDot[2] = equinoctialOrbit.getEquinoctialEyDot();
  385.                 stateVectorDot[3] = equinoctialOrbit.getHxDot();
  386.                 stateVectorDot[4] = equinoctialOrbit.getHyDot();
  387.                 stateVectorDot[5] = equinoctialOrbit.getLDot(type);
  388.             }

  389.         }

  390.         /** {@inheritDoc} */
  391.         @Override
  392.         public EquinoctialOrbit mapArrayToOrbit(final double[] stateVector, final double[] stateVectorDot, final PositionAngleType type,
  393.                                                 final AbsoluteDate date, final double mu, final Frame frame) {
  394.             if (stateVectorDot == null) {
  395.                 // we don't have orbit derivatives
  396.                 return new EquinoctialOrbit(stateVector[0], stateVector[1], stateVector[2],
  397.                                             stateVector[3], stateVector[4], stateVector[5],
  398.                                             type, frame, date, mu);
  399.             } else {
  400.                 // we have orbit derivatives
  401.                 return new EquinoctialOrbit(stateVector[0],    stateVector[1],    stateVector[2],
  402.                                             stateVector[3],    stateVector[4],    stateVector[5],
  403.                                             stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  404.                                             stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  405.                                             type, frame, date, mu);
  406.             }
  407.         }

  408.         /** {@inheritDoc} */
  409.         @Override
  410.         public <T extends CalculusFieldElement<T>> FieldEquinoctialOrbit<T> convertType(final FieldOrbit<T> orbit) {
  411.             return (orbit.getType() == this) ? (FieldEquinoctialOrbit<T>) orbit : new FieldEquinoctialOrbit<>(orbit);
  412.         }

  413.         /** {@inheritDoc} */
  414.         @Override
  415.         public <T extends CalculusFieldElement<T>> void mapOrbitToArray(final FieldOrbit<T> orbit,
  416.                                                                         final PositionAngleType type,
  417.                                                                         final T[] stateVector,
  418.                                                                         final T[] stateVectorDot) {

  419.             final FieldEquinoctialOrbit<T> equinoctialOrbit =
  420.                 (FieldEquinoctialOrbit<T>) OrbitType.EQUINOCTIAL.convertType(orbit);

  421.             stateVector[0] = equinoctialOrbit.getA();
  422.             stateVector[1] = equinoctialOrbit.getEquinoctialEx();
  423.             stateVector[2] = equinoctialOrbit.getEquinoctialEy();
  424.             stateVector[3] = equinoctialOrbit.getHx();
  425.             stateVector[4] = equinoctialOrbit.getHy();
  426.             stateVector[5] = equinoctialOrbit.getL(type);

  427.             if (stateVectorDot != null) {
  428.                 stateVectorDot[0] = equinoctialOrbit.getADot();
  429.                 stateVectorDot[1] = equinoctialOrbit.getEquinoctialExDot();
  430.                 stateVectorDot[2] = equinoctialOrbit.getEquinoctialEyDot();
  431.                 stateVectorDot[3] = equinoctialOrbit.getHxDot();
  432.                 stateVectorDot[4] = equinoctialOrbit.getHyDot();
  433.                 stateVectorDot[5] = equinoctialOrbit.getLDot(type);
  434.             }

  435.         }

  436.         /** {@inheritDoc} */
  437.         @Override
  438.         public <T extends CalculusFieldElement<T>> FieldEquinoctialOrbit<T> mapArrayToOrbit(final T[] stateVector,
  439.                                                                                             final T[] stateVectorDot,
  440.                                                                                             final PositionAngleType type,
  441.                                                                                             final FieldAbsoluteDate<T> date,
  442.                                                                                             final T mu, final Frame frame) {
  443.             if (stateVectorDot == null) {
  444.                 // we don't have orbit derivatives
  445.                 return new FieldEquinoctialOrbit<>(stateVector[0], stateVector[1], stateVector[2],
  446.                                                    stateVector[3], stateVector[4], stateVector[5],
  447.                                                    type, frame, date, mu);
  448.             } else {
  449.                 // we have orbit derivatives
  450.                 return new FieldEquinoctialOrbit<>(stateVector[0],    stateVector[1],    stateVector[2],
  451.                                                    stateVector[3],    stateVector[4],    stateVector[5],
  452.                                                    stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  453.                                                    stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  454.                                                    type, frame, date, mu);
  455.             }
  456.         }

  457.         /** {@inheritDoc} */
  458.         @Override
  459.         public <T extends CalculusFieldElement<T>> FieldEquinoctialOrbit<T> convertToFieldOrbit(final Field<T> field,
  460.                                                                                                 final Orbit orbit) {
  461.             return new FieldEquinoctialOrbit<>(field, EQUINOCTIAL.convertType(orbit));
  462.         }

  463.         /** {@inheritDoc} */
  464.         @Override
  465.         public ParameterDriversList getDrivers(final double dP, final Orbit orbit, final PositionAngleType type) {
  466.             final ParameterDriversList drivers = new ParameterDriversList();
  467.             final double[] array = new double[6];
  468.             mapOrbitToArray(orbit, type, array, null);
  469.             final double[] scale = scale(dP, orbit);
  470.             final String name = type == PositionAngleType.MEAN ?
  471.                                     MEAN_LON_ARG :
  472.                                     type == PositionAngleType.ECCENTRIC ? ECC_LON_ARG : TRUE_LON_ARG;
  473.             drivers.add(new ParameterDriver(A,    array[0], scale[0],  0.0, Double.POSITIVE_INFINITY));
  474.             drivers.add(new ParameterDriver(E_X,  array[1], scale[1], -1.0, 1.0));
  475.             drivers.add(new ParameterDriver(E_Y,  array[2], scale[2], -1.0, 1.0));
  476.             drivers.add(new ParameterDriver(H_X,  array[3], scale[3], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  477.             drivers.add(new ParameterDriver(H_Y,  array[4], scale[4], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  478.             drivers.add(new ParameterDriver(name, array[5], scale[5], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  479.             return drivers;
  480.         }

  481.         /** {@inheritDoc} */
  482.         @Override
  483.         public EquinoctialOrbit normalize(final Orbit orbit, final Orbit reference) {

  484.             // convert input to proper type
  485.             final EquinoctialOrbit eO = convertType(orbit);
  486.             final EquinoctialOrbit eR = convertType(reference);
  487.             final PositionAngleType cachedPositionAngleType = eO.getCachedPositionAngleType();

  488.             // perform normalization
  489.             return new EquinoctialOrbit(eO.getA(),
  490.                                         eO.getEquinoctialEx(),
  491.                                         eO.getEquinoctialEy(),
  492.                                         eO.getHx(),
  493.                                         eO.getHy(),
  494.                                         MathUtils.normalizeAngle(eO.getL(cachedPositionAngleType),
  495.                                         eR.getL(cachedPositionAngleType)),
  496.                                         eO.getADot(),
  497.                                         eO.getEquinoctialExDot(),
  498.                                         eO.getEquinoctialEyDot(),
  499.                                         eO.getHxDot(),
  500.                                         eO.getHyDot(),
  501.                                         eO.getLDot(cachedPositionAngleType),
  502.                                         cachedPositionAngleType,
  503.                                         eO.getFrame(),
  504.                                         eO.getDate(),
  505.                                         eO.getMu());

  506.         }

  507.         /** {@inheritDoc} */
  508.         @Override
  509.         public <T extends CalculusFieldElement<T>> FieldEquinoctialOrbit<T> normalize(final FieldOrbit<T> orbit, final FieldOrbit<T> reference) {

  510.             // convert input to proper type
  511.             final FieldEquinoctialOrbit<T> eO = convertType(orbit);
  512.             final FieldEquinoctialOrbit<T> eR = convertType(reference);
  513.             final PositionAngleType positionAngleType = eO.getCachedPositionAngleType();

  514.             // perform normalization
  515.             if (eO.hasNonKeplerianAcceleration()) {
  516.                 return new FieldEquinoctialOrbit<>(eO.getA(),
  517.                                                    eO.getEquinoctialEx(),
  518.                                                    eO.getEquinoctialEy(),
  519.                                                    eO.getHx(),
  520.                                                    eO.getHy(),
  521.                                                    MathUtils.normalizeAngle(eO.getL(positionAngleType),
  522.                                                            eR.getL(positionAngleType)),
  523.                                                    eO.getADot(),
  524.                                                    eO.getEquinoctialExDot(),
  525.                                                    eO.getEquinoctialEyDot(),
  526.                                                    eO.getHxDot(),
  527.                                                    eO.getHyDot(),
  528.                                                    eO.getLDot(positionAngleType),
  529.                                                    positionAngleType,
  530.                                                    eO.getFrame(),
  531.                                                    eO.getDate(),
  532.                                                    eO.getMu());
  533.             } else {
  534.                 return new FieldEquinoctialOrbit<>(eO.getA(),
  535.                                                    eO.getEquinoctialEx(),
  536.                                                    eO.getEquinoctialEy(),
  537.                                                    eO.getHx(),
  538.                                                    eO.getHy(),
  539.                                                    MathUtils.normalizeAngle(eO.getL(positionAngleType),
  540.                                                            eR.getL(positionAngleType)),
  541.                                                    positionAngleType,
  542.                                                    eO.getFrame(),
  543.                                                    eO.getDate(),
  544.                                                    eO.getMu());
  545.             }

  546.         }

  547.         /** {@inheritDoc} */
  548.         @Override
  549.         public boolean isPositionAngleBased() {
  550.             return true;
  551.         }

  552.     },

  553.     /** Type for orbital representation in {@link KeplerianOrbit} and {@link FieldKeplerianOrbit} parameters. */
  554.     KEPLERIAN {

  555.         /** {@inheritDoc} */
  556.         @Override
  557.         public KeplerianOrbit convertType(final Orbit orbit) {
  558.             return (orbit.getType() == this) ? (KeplerianOrbit) orbit : new KeplerianOrbit(orbit);
  559.         }

  560.         /** {@inheritDoc} */
  561.         @Override
  562.         public void mapOrbitToArray(final Orbit orbit, final PositionAngleType type,
  563.                                     final double[] stateVector, final double[] stateVectorDot) {

  564.             final KeplerianOrbit keplerianOrbit =
  565.                 (KeplerianOrbit) OrbitType.KEPLERIAN.convertType(orbit);

  566.             stateVector[0] = keplerianOrbit.getA();
  567.             stateVector[1] = keplerianOrbit.getE();
  568.             stateVector[2] = keplerianOrbit.getI();
  569.             stateVector[3] = keplerianOrbit.getPerigeeArgument();
  570.             stateVector[4] = keplerianOrbit.getRightAscensionOfAscendingNode();
  571.             stateVector[5] = keplerianOrbit.getAnomaly(type);

  572.             if (stateVectorDot != null) {
  573.                 stateVectorDot[0] = keplerianOrbit.getADot();
  574.                 stateVectorDot[1] = keplerianOrbit.getEDot();
  575.                 stateVectorDot[2] = keplerianOrbit.getIDot();
  576.                 stateVectorDot[3] = keplerianOrbit.getPerigeeArgumentDot();
  577.                 stateVectorDot[4] = keplerianOrbit.getRightAscensionOfAscendingNodeDot();
  578.                 stateVectorDot[5] = keplerianOrbit.getAnomalyDot(type);
  579.             }

  580.         }

  581.         /** {@inheritDoc} */
  582.         @Override
  583.         public KeplerianOrbit mapArrayToOrbit(final double[] stateVector, final double[] stateVectorDot, final PositionAngleType type,
  584.                                               final AbsoluteDate date, final double mu, final Frame frame) {
  585.             if (stateVectorDot == null) {
  586.                 // we don't have orbit derivatives
  587.                 return new KeplerianOrbit(stateVector[0], stateVector[1], stateVector[2],
  588.                                           stateVector[3], stateVector[4], stateVector[5],
  589.                                           type, frame, date, mu);
  590.             } else {
  591.                 // we have orbit derivatives
  592.                 return new KeplerianOrbit(stateVector[0],    stateVector[1],    stateVector[2],
  593.                                           stateVector[3],    stateVector[4],    stateVector[5],
  594.                                           stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  595.                                           stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  596.                                           type, frame, date, mu);
  597.             }
  598.         }

  599.         /** {@inheritDoc} */
  600.         @Override
  601.         public <T extends CalculusFieldElement<T>> FieldKeplerianOrbit<T> convertType(final FieldOrbit<T> orbit) {
  602.             return (orbit.getType() == this) ? (FieldKeplerianOrbit<T>) orbit : new FieldKeplerianOrbit<>(orbit);
  603.         }

  604.         /** {@inheritDoc} */
  605.         @Override
  606.         public <T extends CalculusFieldElement<T>> void mapOrbitToArray(final FieldOrbit<T> orbit,
  607.                                                                         final PositionAngleType type,
  608.                                                                         final T[] stateVector,
  609.                                                                         final T[] stateVectorDot) {
  610.             final FieldKeplerianOrbit<T> keplerianOrbit =
  611.                             (FieldKeplerianOrbit<T>) OrbitType.KEPLERIAN.convertType(orbit);

  612.             stateVector[0] = keplerianOrbit.getA();
  613.             stateVector[1] = keplerianOrbit.getE();
  614.             stateVector[2] = keplerianOrbit.getI();
  615.             stateVector[3] = keplerianOrbit.getPerigeeArgument();
  616.             stateVector[4] = keplerianOrbit.getRightAscensionOfAscendingNode();
  617.             stateVector[5] = keplerianOrbit.getAnomaly(type);

  618.             if (stateVectorDot != null) {
  619.                 stateVectorDot[0] = keplerianOrbit.getADot();
  620.                 stateVectorDot[1] = keplerianOrbit.getEDot();
  621.                 stateVectorDot[2] = keplerianOrbit.getIDot();
  622.                 stateVectorDot[3] = keplerianOrbit.getPerigeeArgumentDot();
  623.                 stateVectorDot[4] = keplerianOrbit.getRightAscensionOfAscendingNodeDot();
  624.                 stateVectorDot[5] = keplerianOrbit.getAnomalyDot(type);
  625.             }

  626.         }

  627.         /** {@inheritDoc} */
  628.         @Override
  629.         public <T extends CalculusFieldElement<T>> FieldKeplerianOrbit<T> mapArrayToOrbit(final T[] stateVector,
  630.                                                                                           final T[] stateVectorDot,
  631.                                                                                           final PositionAngleType type,
  632.                                                                                           final FieldAbsoluteDate<T> date,
  633.                                                                                           final T mu, final Frame frame) {
  634.             if (stateVectorDot == null) {
  635.                 // we don't have orbit derivatives
  636.                 return new FieldKeplerianOrbit<>(stateVector[0], stateVector[1], stateVector[2],
  637.                                                  stateVector[3], stateVector[4], stateVector[5],
  638.                                                  type, frame, date, mu);
  639.             } else {
  640.                 // we have orbit derivatives
  641.                 return new FieldKeplerianOrbit<>(stateVector[0],    stateVector[1],    stateVector[2],
  642.                                                  stateVector[3],    stateVector[4],    stateVector[5],
  643.                                                  stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  644.                                                  stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  645.                                                  type, frame, date, mu);
  646.             }
  647.         }

  648.         /** {@inheritDoc} */
  649.         @Override
  650.         public <T extends CalculusFieldElement<T>> FieldKeplerianOrbit<T> convertToFieldOrbit(final Field<T> field,
  651.                                                                                               final Orbit orbit) {
  652.             return new FieldKeplerianOrbit<>(field, KEPLERIAN.convertType(orbit));
  653.         }

  654.         /** {@inheritDoc} */
  655.         @Override
  656.         public ParameterDriversList getDrivers(final double dP, final Orbit orbit, final PositionAngleType type) {
  657.             final ParameterDriversList drivers = new ParameterDriversList();
  658.             final double[] array = new double[6];
  659.             mapOrbitToArray(orbit, type, array, null);
  660.             final double[] scale = scale(dP, orbit);
  661.             final String name = type == PositionAngleType.MEAN ?
  662.                                     MEAN_ANOM :
  663.                                     type == PositionAngleType.ECCENTRIC ? ECC_ANOM : TRUE_ANOM;
  664.             drivers.add(new ParameterDriver(A,    array[0], scale[0],  0.0, Double.POSITIVE_INFINITY));
  665.             drivers.add(new ParameterDriver(ECC,  array[1], scale[1],  0.0, 1.0));
  666.             drivers.add(new ParameterDriver(INC,  array[2], scale[2],  0.0, FastMath.PI));
  667.             drivers.add(new ParameterDriver(PA,   array[3], scale[3], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  668.             drivers.add(new ParameterDriver(RAAN, array[4], scale[4], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  669.             drivers.add(new ParameterDriver(name, array[5], scale[5], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  670.             return drivers;
  671.         }

  672.         /** {@inheritDoc} */
  673.         @Override
  674.         public KeplerianOrbit normalize(final Orbit orbit, final Orbit reference) {

  675.             // convert input to proper type
  676.             final KeplerianOrbit kO = convertType(orbit);
  677.             final KeplerianOrbit kR = convertType(reference);
  678.             final PositionAngleType cachedPositionAngleType = kO.getCachedPositionAngleType();

  679.             // perform normalization
  680.             return new KeplerianOrbit(kO.getA(),
  681.                                       kO.getE(),
  682.                                       kO.getI(),
  683.                                       MathUtils.normalizeAngle(kO.getPerigeeArgument(), kR.getPerigeeArgument()),
  684.                                       MathUtils.normalizeAngle(kO.getRightAscensionOfAscendingNode(),
  685.                                               kR.getRightAscensionOfAscendingNode()),
  686.                                       MathUtils.normalizeAngle(kO.getAnomaly(cachedPositionAngleType),
  687.                                               kR.getAnomaly(cachedPositionAngleType)),
  688.                                       kO.getADot(),
  689.                                       kO.getEDot(),
  690.                                       kO.getIDot(),
  691.                                       kO.getPerigeeArgumentDot(),
  692.                                       kO.getRightAscensionOfAscendingNodeDot(),
  693.                                       kO.getAnomalyDot(cachedPositionAngleType),
  694.                                       cachedPositionAngleType,
  695.                                       kO.getFrame(),
  696.                                       kO.getDate(),
  697.                                       kO.getMu());

  698.         }

  699.         /** {@inheritDoc} */
  700.         @Override
  701.         public <T extends CalculusFieldElement<T>> FieldKeplerianOrbit<T> normalize(final FieldOrbit<T> orbit, final FieldOrbit<T> reference) {

  702.             // convert input to proper type
  703.             final FieldKeplerianOrbit<T> kO = convertType(orbit);
  704.             final FieldKeplerianOrbit<T> kR = convertType(reference);
  705.             final PositionAngleType positionAngleType = kO.getCachedPositionAngleType();

  706.             // perform normalization
  707.             if (kO.hasNonKeplerianAcceleration()) {
  708.                 return new FieldKeplerianOrbit<>(kO.getA(),
  709.                                                  kO.getE(),
  710.                                                  kO.getI(),
  711.                                                  MathUtils.normalizeAngle(kO.getPerigeeArgument(), kR.getPerigeeArgument()),
  712.                                                  MathUtils.normalizeAngle(kO.getRightAscensionOfAscendingNode(),
  713.                                                          kR.getRightAscensionOfAscendingNode()),
  714.                                                  MathUtils.normalizeAngle(kO.getAnomaly(positionAngleType),
  715.                                                          kR.getAnomaly(positionAngleType)),
  716.                                                  kO.getADot(),
  717.                                                  kO.getEDot(),
  718.                                                  kO.getIDot(),
  719.                                                  kO.getPerigeeArgumentDot(),
  720.                                                  kO.getRightAscensionOfAscendingNodeDot(),
  721.                                                  kO.getAnomalyDot(positionAngleType),
  722.                                                  positionAngleType,
  723.                                                  kO.getFrame(),
  724.                                                  kO.getDate(),
  725.                                                  kO.getMu());
  726.             } else {
  727.                 return new FieldKeplerianOrbit<>(kO.getA(),
  728.                                                  kO.getE(),
  729.                                                  kO.getI(),
  730.                                                  MathUtils.normalizeAngle(kO.getPerigeeArgument(), kR.getPerigeeArgument()),
  731.                                                  MathUtils.normalizeAngle(kO.getRightAscensionOfAscendingNode(),
  732.                                                          kR.getRightAscensionOfAscendingNode()),
  733.                                                  MathUtils.normalizeAngle(kO.getAnomaly(positionAngleType),
  734.                                                          kR.getAnomaly(positionAngleType)),
  735.                                                  positionAngleType,
  736.                                                  kO.getFrame(),
  737.                                                  kO.getDate(),
  738.                                                  kO.getMu());
  739.             }

  740.         }

  741.         /** {@inheritDoc} */
  742.         @Override
  743.         public boolean isPositionAngleBased() {
  744.             return true;
  745.         }

  746.     };

  747.     /** Name for position along X. */
  748.     public static final String POS_X = "Px";

  749.     /** Name for position along Y. */
  750.     public static final String POS_Y = "Py";

  751.     /** Name for position along Z. */
  752.     public static final String POS_Z = "Pz";

  753.     /** Name for velocity along X. */
  754.     public static final String VEL_X = "Vx";

  755.     /** Name for velocity along Y. */
  756.     public static final String VEL_Y = "Vy";

  757.     /** Name for velocity along Z. */
  758.     public static final String VEL_Z = "Vz";

  759.     /** Name for semi major axis. */
  760.     public static final String A     = "a";

  761.     /** Name for eccentricity. */
  762.     public static final String ECC   = "e";

  763.     /** Name for eccentricity vector first component. */
  764.     public static final String E_X   = "ex";

  765.     /** Name for eccentricity vector second component. */
  766.     public static final String E_Y   = "ey";

  767.     /** Name for inclination. */
  768.     public static final String INC   = "i";

  769.     /** Name for inclination vector first component. */
  770.     public static final String H_X   = "hx";

  771.     /** Name for inclination vector second component . */
  772.     public static final String H_Y   = "hy";

  773.     /** Name for perigee argument. */
  774.     public static final String PA    = "ω";

  775.     /** Name for right ascension of ascending node. */
  776.     public static final String RAAN    = "Ω";

  777.     /** Name for mean anomaly. */
  778.     public static final String MEAN_ANOM = "M";

  779.     /** Name for eccentric anomaly. */
  780.     public static final String ECC_ANOM  = "E";

  781.     /** Name for mean anomaly. */
  782.     public static final String TRUE_ANOM = "v";

  783.     /** Name for mean argument of latitude. */
  784.     public static final String MEAN_LAT_ARG = "αM";

  785.     /** Name for eccentric argument of latitude. */
  786.     public static final String ECC_LAT_ARG  = "αE";

  787.     /** Name for mean argument of latitude. */
  788.     public static final String TRUE_LAT_ARG = "αv";

  789.     /** Name for mean argument of longitude. */
  790.     public static final String MEAN_LON_ARG = "λM";

  791.     /** Name for eccentric argument of longitude. */
  792.     public static final String ECC_LON_ARG  = "λE";

  793.     /** Name for mean argument of longitude. */
  794.     public static final String TRUE_LON_ARG = "λv";

  795.     /** Convert an orbit to the instance type.
  796.      * <p>
  797.      * The returned orbit is the specified instance itself if its type already matches,
  798.      * otherwise, a new orbit of the proper type created
  799.      * </p>
  800.      * @param orbit orbit to convert
  801.      * @return converted orbit with type guaranteed to match (so it can be cast safely)
  802.      */
  803.     public abstract Orbit convertType(Orbit orbit);

  804.     /** Convert orbit to state array.
  805.      * <p>
  806.      * Note that all implementations of this method <em>must</em> be consistent with the
  807.      * implementation of the {@link org.orekit.orbits.Orbit#getJacobianWrtCartesian(
  808.      * PositionAngleType, double[][]) Orbit.getJacobianWrtCartesian}
  809.      * method for the corresponding orbit type in terms of parameters order and meaning.
  810.      * </p>
  811.      * @param orbit orbit to map
  812.      * @param type type of the angle
  813.      * @param stateVector flat array into which the state vector should be mapped
  814.      * (it can have more than 6 elements, extra elements are untouched)
  815.      * @param stateVectorDot flat array into which the state vector derivative should be mapped
  816.      * (it can be null if derivatives are not desired, and it can have more than 6 elements, extra elements are untouched)
  817.      */
  818.     public abstract void mapOrbitToArray(Orbit orbit, PositionAngleType type, double[] stateVector, double[] stateVectorDot);

  819.      /** Convert state array to orbital parameters.
  820.      * <p>
  821.      * Note that all implementations of this method <em>must</em> be consistent with the
  822.      * implementation of the {@link org.orekit.orbits.Orbit#getJacobianWrtCartesian(
  823.      * PositionAngleType, double[][]) Orbit.getJacobianWrtCartesian}
  824.      * method for the corresponding orbit type in terms of parameters order and meaning.
  825.      * </p>
  826.      * @param array state as a flat array
  827.      * (it can have more than 6 elements, extra elements are ignored)
  828.      * @param arrayDot state derivative as a flat array
  829.      * (it can be null, in which case Keplerian motion is assumed,
  830.      * and it can have more than 6 elements, extra elements are ignored)
  831.      * @param type type of the angle
  832.      * @param date integration date
  833.      * @param mu central attraction coefficient used for propagation (m³/s²)
  834.      * @param frame frame in which integration is performed
  835.      * @return orbit corresponding to the flat array as a space dynamics object
  836.      */
  837.     public abstract Orbit mapArrayToOrbit(double[] array, double[] arrayDot, PositionAngleType type,
  838.                                           AbsoluteDate date, double mu, Frame frame);

  839.     /** Convert an orbit to the instance type.
  840.      * <p>
  841.      * The returned orbit is the specified instance itself if its type already matches,
  842.      * otherwise, a new orbit of the proper type created
  843.      * </p>
  844.      * @param <T> CalculusFieldElement used
  845.      * @param orbit orbit to convert
  846.      * @return converted orbit with type guaranteed to match (so it can be cast safely)
  847.      */
  848.     public abstract <T extends CalculusFieldElement<T>> FieldOrbit<T> convertType(FieldOrbit<T> orbit);

  849.     /** Convert orbit to state array.
  850.      * <p>
  851.      * Note that all implementations of this method <em>must</em> be consistent with the
  852.      * implementation of the {@link org.orekit.orbits.Orbit#getJacobianWrtCartesian(
  853.      * PositionAngleType, double[][]) Orbit.getJacobianWrtCartesian}
  854.      * method for the corresponding orbit type in terms of parameters order and meaning.
  855.      * </p>
  856.      * @param <T> CalculusFieldElement used
  857.      * @param orbit orbit to map
  858.      * @param type type of the angle
  859.      * @param stateVector flat array into which the state vector should be mapped
  860.      * (it can have more than 6 elements, extra elements are untouched)
  861.      * @param stateVectorDot flat array into which the state vector derivative should be mapped
  862.      * (it can be null if derivatives are not desired, and it can have more than 6 elements, extra elements are untouched)
  863.      */
  864.     public abstract <T extends CalculusFieldElement<T>>void mapOrbitToArray(FieldOrbit<T> orbit, PositionAngleType type,
  865.                                                                             T[] stateVector, T[] stateVectorDot);


  866.     /** Convert state array to orbital parameters.
  867.      * <p>
  868.      * Note that all implementations of this method <em>must</em> be consistent with the
  869.      * implementation of the {@link org.orekit.orbits.Orbit#getJacobianWrtCartesian(
  870.      * PositionAngleType, double[][]) Orbit.getJacobianWrtCartesian}
  871.      * method for the corresponding orbit type in terms of parameters order and meaning.
  872.      * </p>
  873.      * @param <T> CalculusFieldElement used
  874.      * @param array state as a flat array
  875.      * (it can have more than 6 elements, extra elements are ignored)
  876.      * @param arrayDot state derivative as a flat array
  877.      * (it can be null, in which case Keplerian motion is assumed,
  878.      * @param type type of the angle
  879.      * @param date integration date
  880.      * @param mu central attraction coefficient used for propagation (m³/s²)
  881.      * @param frame frame in which integration is performed
  882.      * @return orbit corresponding to the flat array as a space dynamics object
  883.      */
  884.     public abstract <T extends CalculusFieldElement<T>> FieldOrbit<T> mapArrayToOrbit(T[] array,
  885.                                                                                       T[] arrayDot,
  886.                                                                                       PositionAngleType type,
  887.                                                                                       FieldAbsoluteDate<T> date,
  888.                                                                                       T mu, Frame frame);

  889.     /** Convert an orbit to the "Fielded" instance type.
  890.      * @param <T> CalculusFieldElement used
  891.      * @param field CalculusField
  892.      * @param orbit base orbit
  893.      * @return converted FieldOrbit with type guaranteed to match (so it can be cast safely)
  894.      * @since 12.0
  895.      */
  896.     public abstract <T extends CalculusFieldElement<T>> FieldOrbit<T> convertToFieldOrbit(Field<T> field,
  897.                                                                                            Orbit orbit);

  898.     /** Get parameters drivers initialized from a reference orbit.
  899.      * @param dP user specified position error
  900.      * @param orbit reference orbit
  901.      * @param type type of the angle
  902.      * @return parameters drivers initialized from reference orbit
  903.      */
  904.     public abstract ParameterDriversList getDrivers(double dP, Orbit orbit,
  905.                                                     PositionAngleType type);

  906.     /** Normalize one orbit with respect to a reference one.
  907.      * <p>
  908.      * Given a, angular component ζ of an orbit and the corresponding
  909.      * angular component ζᵣ in the reference orbit, the angular component
  910.      * ζₙ of the normalized orbit will be ζₙ = ζ + 2kπ
  911.      * where k is chosen such that ζᵣ - π ≤ ζₙ ≤ ζᵣ + π. This is intended
  912.      * to avoid too large discontinuities and is particularly useful
  913.      * for normalizing the orbit after an impulsive maneuver with respect
  914.      * to the reference picked up before the maneuver.
  915.      * </p>
  916.      * @param <T> CalculusFieldElement used
  917.      * @param orbit orbit to normalize
  918.      * @param reference reference orbit
  919.      * @return normalized orbit (the type is guaranteed to match {@link OrbitType})
  920.      * @since 11.1
  921.      */
  922.     public abstract <T extends CalculusFieldElement<T>> FieldOrbit<T> normalize(FieldOrbit<T> orbit,
  923.                                                                                 FieldOrbit<T> reference);

  924.     /** Normalize one orbit with respect to a reference one.
  925.      * <p>
  926.      * Given a, angular component ζ of an orbit and the corresponding
  927.      * angular component ζᵣ in the reference orbit, the angular component
  928.      * ζₙ of the normalized orbit will be ζₙ = ζ + 2kπ
  929.      * where k is chosen such that ζᵣ - π ≤ ζₙ ≤ ζᵣ + π. This is intended
  930.      * to avoid too large discontinuities and is particularly useful
  931.      * for normalizing the orbit after an impulsive maneuver with respect
  932.      * to the reference picked up before the maneuver.
  933.      * </p>
  934.      * @param orbit orbit to normalize
  935.      * @param reference reference orbit
  936.      * @return normalized orbit (the type is guaranteed to match {@link OrbitType})
  937.      * @since 11.1
  938.      */
  939.     public abstract Orbit normalize(Orbit orbit, Orbit reference);

  940.     /** Tells if the orbit type is based on position angles or not.
  941.      * @return true if based on {@link PositionAngleType}
  942.      * @since 12.0
  943.      */
  944.     public abstract boolean isPositionAngleBased();

  945.     /** Compute scaling factor for parameters drivers.
  946.      * <p>
  947.      * The scales are estimated from partial derivatives properties of orbits,
  948.      * starting from a scalar position error specified by the user.
  949.      * Considering the energy conservation equation V = sqrt(mu (2/r - 1/a)),
  950.      * we get at constant energy (i.e. on a Keplerian trajectory):
  951.      * <pre>
  952.      * V r² |dV| = mu |dr|
  953.      * </pre>
  954.      * <p> So we deduce a scalar velocity error consistent with the position error.
  955.      * From here, we apply orbits Jacobians matrices to get consistent scales
  956.      * on orbital parameters.
  957.      *
  958.      * @param dP user specified position error
  959.      * @param orbit reference orbit
  960.      * @return scaling factor array
  961.      */
  962.     protected double[] scale(final double dP, final Orbit orbit) {

  963.         // estimate the scalar velocity error
  964.         final PVCoordinates pv = orbit.getPVCoordinates();
  965.         final double r2 = pv.getPosition().getNormSq();
  966.         final double v  = pv.getVelocity().getNorm();
  967.         final double dV = orbit.getMu() * dP / (v * r2);

  968.         final double[] scale = new double[6];

  969.         // convert the orbit to the desired type
  970.         final double[][] jacobian = new double[6][6];
  971.         final Orbit converted = convertType(orbit);
  972.         converted.getJacobianWrtCartesian(PositionAngleType.TRUE, jacobian);

  973.         for (int i = 0; i < 6; ++i) {
  974.             final double[] row = jacobian[i];
  975.             scale[i] = FastMath.abs(row[0]) * dP +
  976.                        FastMath.abs(row[1]) * dP +
  977.                        FastMath.abs(row[2]) * dP +
  978.                        FastMath.abs(row[3]) * dV +
  979.                        FastMath.abs(row[4]) * dV +
  980.                        FastMath.abs(row[5]) * dV;
  981.             if (Double.isNaN(scale[i])) {
  982.                 throw new OrekitException(OrekitMessages.SINGULAR_JACOBIAN_FOR_ORBIT_TYPE, this);
  983.             }
  984.         }

  985.         return scale;

  986.     }

  987. }