OrbitType.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.orbits;

  18. import java.util.Arrays;

  19. import org.hipparchus.CalculusFieldElement;
  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 orbital} parameters types.
  35.  */
  36. public enum OrbitType {

  37.     /** Type for propagation in {@link CartesianOrbit Cartesian 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 PositionAngle 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 PositionAngle 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 PositionAngle 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 PositionAngle 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 ParameterDriversList getDrivers(final double dP, final Orbit orbit, final PositionAngle type) {
  135.             final ParameterDriversList drivers = new ParameterDriversList();
  136.             final double[] array = new double[6];
  137.             mapOrbitToArray(orbit, type, array, null);
  138.             final double[] scale = scale(dP, orbit);
  139.             drivers.add(new ParameterDriver(POS_X, array[0], scale[0], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  140.             drivers.add(new ParameterDriver(POS_Y, array[1], scale[1], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  141.             drivers.add(new ParameterDriver(POS_Z, array[2], scale[2], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  142.             drivers.add(new ParameterDriver(VEL_X, array[3], scale[3], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  143.             drivers.add(new ParameterDriver(VEL_Y, array[4], scale[4], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  144.             drivers.add(new ParameterDriver(VEL_Z, array[5], scale[5], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  145.             return drivers;
  146.         }

  147.         /** {@inheritDoc} */
  148.         @Override
  149.         public CartesianOrbit normalize(final Orbit orbit, final Orbit reference) {
  150.             // no angular parameters need normalization
  151.             return convertType(orbit);
  152.         }

  153.         /** {@inheritDoc} */
  154.         @Override
  155.         public <T extends CalculusFieldElement<T>> FieldCartesianOrbit<T> normalize(final FieldOrbit<T> orbit, final FieldOrbit<T> reference) {
  156.             // no angular parameters need normalization
  157.             return convertType(orbit);
  158.         }

  159.     },

  160.     /** Type for propagation in {@link CircularOrbit circular parameters}. */
  161.     CIRCULAR {

  162.         /** {@inheritDoc} */
  163.         @Override
  164.         public CircularOrbit convertType(final Orbit orbit) {
  165.             return (orbit.getType() == this) ? (CircularOrbit) orbit : new CircularOrbit(orbit);
  166.         }

  167.         /** {@inheritDoc} */
  168.         @Override
  169.         public void mapOrbitToArray(final Orbit orbit, final PositionAngle type,
  170.                                     final double[] stateVector, final double[] stateVectorDot) {

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

  172.             stateVector[0] = circularOrbit.getA();
  173.             stateVector[1] = circularOrbit.getCircularEx();
  174.             stateVector[2] = circularOrbit.getCircularEy();
  175.             stateVector[3] = circularOrbit.getI();
  176.             stateVector[4] = circularOrbit.getRightAscensionOfAscendingNode();
  177.             stateVector[5] = circularOrbit.getAlpha(type);

  178.             if (stateVectorDot != null) {
  179.                 if (orbit.hasDerivatives()) {
  180.                     stateVectorDot[0] = circularOrbit.getADot();
  181.                     stateVectorDot[1] = circularOrbit.getCircularExDot();
  182.                     stateVectorDot[2] = circularOrbit.getCircularEyDot();
  183.                     stateVectorDot[3] = circularOrbit.getIDot();
  184.                     stateVectorDot[4] = circularOrbit.getRightAscensionOfAscendingNodeDot();
  185.                     stateVectorDot[5] = circularOrbit.getAlphaDot(type);
  186.                 } else {
  187.                     Arrays.fill(stateVectorDot, 0, 6, Double.NaN);
  188.                 }
  189.             }

  190.         }

  191.         /** {@inheritDoc} */
  192.         @Override
  193.         public CircularOrbit mapArrayToOrbit(final double[] stateVector, final double[] stateVectorDot, final PositionAngle type,
  194.                                              final AbsoluteDate date, final double mu, final Frame frame) {
  195.             if (stateVectorDot == null) {
  196.                 // we don't have orbit derivatives
  197.                 return new CircularOrbit(stateVector[0], stateVector[1], stateVector[2],
  198.                                          stateVector[3], stateVector[4], stateVector[5],
  199.                                          type, frame, date, mu);
  200.             } else {
  201.                 // we have orbit derivatives
  202.                 return new CircularOrbit(stateVector[0],    stateVector[1],    stateVector[2],
  203.                                          stateVector[3],    stateVector[4],    stateVector[5],
  204.                                          stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  205.                                          stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  206.                                          type, frame, date, mu);
  207.             }
  208.         }

  209.         /** {@inheritDoc} */
  210.         @Override
  211.         public <T extends CalculusFieldElement<T>> FieldCircularOrbit<T> convertType(final FieldOrbit<T> orbit) {
  212.             return (orbit.getType() == this) ? (FieldCircularOrbit<T>) orbit : new FieldCircularOrbit<>(orbit);
  213.         }

  214.         /** {@inheritDoc} */
  215.         @Override
  216.         public <T extends CalculusFieldElement<T>> void mapOrbitToArray(final FieldOrbit<T> orbit,
  217.                                                                         final PositionAngle type,
  218.                                                                         final T[] stateVector,
  219.                                                                         final T[] stateVectorDot) {

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

  221.             stateVector[0] = circularOrbit.getA();
  222.             stateVector[1] = circularOrbit.getCircularEx();
  223.             stateVector[2] = circularOrbit.getCircularEy();
  224.             stateVector[3] = circularOrbit.getI();
  225.             stateVector[4] = circularOrbit.getRightAscensionOfAscendingNode();
  226.             stateVector[5] = circularOrbit.getAlpha(type);

  227.             if (stateVectorDot != null) {
  228.                 if (orbit.hasDerivatives()) {
  229.                     stateVectorDot[0] = circularOrbit.getADot();
  230.                     stateVectorDot[1] = circularOrbit.getCircularExDot();
  231.                     stateVectorDot[2] = circularOrbit.getCircularEyDot();
  232.                     stateVectorDot[3] = circularOrbit.getIDot();
  233.                     stateVectorDot[4] = circularOrbit.getRightAscensionOfAscendingNodeDot();
  234.                     stateVectorDot[5] = circularOrbit.getAlphaDot(type);
  235.                 } else {
  236.                     Arrays.fill(stateVectorDot, 0, 6, orbit.getDate().getField().getZero().add(Double.NaN));
  237.                 }
  238.             }

  239.         }

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

  260.         /** {@inheritDoc} */
  261.         @Override
  262.         public ParameterDriversList getDrivers(final double dP, final Orbit orbit, final PositionAngle type) {
  263.             final ParameterDriversList drivers = new ParameterDriversList();
  264.             final double[] array = new double[6];
  265.             mapOrbitToArray(orbit, type, array, null);
  266.             final double[] scale = scale(dP, orbit);
  267.             final String name = type == PositionAngle.MEAN ?
  268.                                     MEAN_LAT_ARG :
  269.                                     type == PositionAngle.ECCENTRIC ? ECC_LAT_ARG : TRUE_LAT_ARG;
  270.             drivers.add(new ParameterDriver(A,    array[0], scale[0],  0.0, Double.POSITIVE_INFINITY));
  271.             drivers.add(new ParameterDriver(E_X,  array[1], scale[1], -1.0, 1.0));
  272.             drivers.add(new ParameterDriver(E_Y,  array[2], scale[2], -1.0, 1.0));
  273.             drivers.add(new ParameterDriver(INC,  array[3], scale[3],  0.0, FastMath.PI));
  274.             drivers.add(new ParameterDriver(RAAN, array[4], scale[4], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  275.             drivers.add(new ParameterDriver(name, array[5], scale[5], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  276.             return drivers;
  277.         }

  278.         /** {@inheritDoc} */
  279.         @Override
  280.         public CircularOrbit normalize(final Orbit orbit, final Orbit reference) {

  281.             // convert input to proper type
  282.             final CircularOrbit cO = convertType(orbit);
  283.             final CircularOrbit cR = convertType(reference);

  284.             // perform normalization
  285.             if (cO.hasDerivatives()) {
  286.                 return new CircularOrbit(cO.getA(),
  287.                                          cO.getCircularEx(),
  288.                                          cO.getCircularEy(),
  289.                                          cO.getI(),
  290.                                          MathUtils.normalizeAngle(cO.getRightAscensionOfAscendingNode(), cR.getRightAscensionOfAscendingNode()),
  291.                                          MathUtils.normalizeAngle(cO.getAlphaV(), cR.getAlphaV()),
  292.                                          cO.getADot(),
  293.                                          cO.getCircularExDot(),
  294.                                          cO.getCircularEyDot(),
  295.                                          cO.getIDot(),
  296.                                          cO.getRightAscensionOfAscendingNodeDot(),
  297.                                          cO.getAlphaVDot(),
  298.                                          PositionAngle.TRUE,
  299.                                          cO.getFrame(),
  300.                                          cO.getDate(),
  301.                                          cO.getMu());
  302.             } else {
  303.                 return new CircularOrbit(cO.getA(),
  304.                                          cO.getCircularEx(),
  305.                                          cO.getCircularEy(),
  306.                                          cO.getI(),
  307.                                          MathUtils.normalizeAngle(cO.getRightAscensionOfAscendingNode(), cR.getRightAscensionOfAscendingNode()),
  308.                                          MathUtils.normalizeAngle(cO.getAlphaV(), cR.getAlphaV()),
  309.                                          PositionAngle.TRUE,
  310.                                          cO.getFrame(),
  311.                                          cO.getDate(),
  312.                                          cO.getMu());
  313.             }

  314.         }

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

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

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

  351.         }

  352.     },

  353.     /** Type for propagation in {@link EquinoctialOrbit equinoctial parameters}. */
  354.     EQUINOCTIAL {

  355.         /** {@inheritDoc} */
  356.         @Override
  357.         public EquinoctialOrbit convertType(final Orbit orbit) {
  358.             return (orbit.getType() == this) ? (EquinoctialOrbit) orbit : new EquinoctialOrbit(orbit);
  359.         }

  360.         /** {@inheritDoc} */
  361.         @Override
  362.         public void mapOrbitToArray(final Orbit orbit, final PositionAngle type,
  363.                                     final double[] stateVector, final double[] stateVectorDot) {

  364.             final EquinoctialOrbit equinoctialOrbit =
  365.                 (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(orbit);

  366.             stateVector[0] = equinoctialOrbit.getA();
  367.             stateVector[1] = equinoctialOrbit.getEquinoctialEx();
  368.             stateVector[2] = equinoctialOrbit.getEquinoctialEy();
  369.             stateVector[3] = equinoctialOrbit.getHx();
  370.             stateVector[4] = equinoctialOrbit.getHy();
  371.             stateVector[5] = equinoctialOrbit.getL(type);

  372.             if (stateVectorDot != null) {
  373.                 if (orbit.hasDerivatives()) {
  374.                     stateVectorDot[0] = equinoctialOrbit.getADot();
  375.                     stateVectorDot[1] = equinoctialOrbit.getEquinoctialExDot();
  376.                     stateVectorDot[2] = equinoctialOrbit.getEquinoctialEyDot();
  377.                     stateVectorDot[3] = equinoctialOrbit.getHxDot();
  378.                     stateVectorDot[4] = equinoctialOrbit.getHyDot();
  379.                     stateVectorDot[5] = equinoctialOrbit.getLDot(type);
  380.                 } else {
  381.                     Arrays.fill(stateVectorDot, 0, 6, Double.NaN);
  382.                 }
  383.             }

  384.         }

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

  403.         /** {@inheritDoc} */
  404.         @Override
  405.         public <T extends CalculusFieldElement<T>> FieldEquinoctialOrbit<T> convertType(final FieldOrbit<T> orbit) {
  406.             return (orbit.getType() == this) ? (FieldEquinoctialOrbit<T>) orbit : new FieldEquinoctialOrbit<>(orbit);
  407.         }

  408.         /** {@inheritDoc} */
  409.         @Override
  410.         public <T extends CalculusFieldElement<T>> void mapOrbitToArray(final FieldOrbit<T> orbit,
  411.                                                                         final PositionAngle type,
  412.                                                                         final T[] stateVector,
  413.                                                                         final T[] stateVectorDot) {

  414.             final FieldEquinoctialOrbit<T> equinoctialOrbit =
  415.                 (FieldEquinoctialOrbit<T>) OrbitType.EQUINOCTIAL.convertType(orbit);

  416.             stateVector[0] = equinoctialOrbit.getA();
  417.             stateVector[1] = equinoctialOrbit.getEquinoctialEx();
  418.             stateVector[2] = equinoctialOrbit.getEquinoctialEy();
  419.             stateVector[3] = equinoctialOrbit.getHx();
  420.             stateVector[4] = equinoctialOrbit.getHy();
  421.             stateVector[5] = equinoctialOrbit.getL(type);

  422.             if (stateVectorDot != null) {
  423.                 if (orbit.hasDerivatives()) {
  424.                     stateVectorDot[0] = equinoctialOrbit.getADot();
  425.                     stateVectorDot[1] = equinoctialOrbit.getEquinoctialExDot();
  426.                     stateVectorDot[2] = equinoctialOrbit.getEquinoctialEyDot();
  427.                     stateVectorDot[3] = equinoctialOrbit.getHxDot();
  428.                     stateVectorDot[4] = equinoctialOrbit.getHyDot();
  429.                     stateVectorDot[5] = equinoctialOrbit.getLDot(type);
  430.                 } else {
  431.                     Arrays.fill(stateVectorDot, 0, 6, orbit.getDate().getField().getZero().add(Double.NaN));
  432.                 }
  433.             }

  434.         }

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

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

  474.         /** {@inheritDoc} */
  475.         @Override
  476.         public EquinoctialOrbit normalize(final Orbit orbit, final Orbit reference) {

  477.             // convert input to proper type
  478.             final EquinoctialOrbit eO = convertType(orbit);
  479.             final EquinoctialOrbit eR = convertType(reference);

  480.             // perform normalization
  481.             if (eO.hasDerivatives()) {
  482.                 return new EquinoctialOrbit(eO.getA(),
  483.                                             eO.getEquinoctialEx(),
  484.                                             eO.getEquinoctialEy(),
  485.                                             eO.getHx(),
  486.                                             eO.getHy(),
  487.                                             MathUtils.normalizeAngle(eO.getLv(), eR.getLv()),
  488.                                             eO.getADot(),
  489.                                             eO.getEquinoctialExDot(),
  490.                                             eO.getEquinoctialEyDot(),
  491.                                             eO.getHxDot(),
  492.                                             eO.getHyDot(),
  493.                                             eO.getLvDot(),
  494.                                             PositionAngle.TRUE,
  495.                                             eO.getFrame(),
  496.                                             eO.getDate(),
  497.                                             eO.getMu());
  498.             } else {
  499.                 return new EquinoctialOrbit(eO.getA(),
  500.                                             eO.getEquinoctialEx(),
  501.                                             eO.getEquinoctialEy(),
  502.                                             eO.getHx(),
  503.                                             eO.getHy(),
  504.                                             MathUtils.normalizeAngle(eO.getLv(), eR.getLv()),
  505.                                             PositionAngle.TRUE,
  506.                                             eO.getFrame(),
  507.                                             eO.getDate(),
  508.                                             eO.getMu());
  509.             }

  510.         }

  511.         /** {@inheritDoc} */
  512.         @Override
  513.         public <T extends CalculusFieldElement<T>> FieldEquinoctialOrbit<T> normalize(final FieldOrbit<T> orbit, final FieldOrbit<T> reference) {

  514.             // convert input to proper type
  515.             final FieldEquinoctialOrbit<T> eO = convertType(orbit);
  516.             final FieldEquinoctialOrbit<T> eR = convertType(reference);

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

  547.         }

  548.     },

  549.     /** Type for propagation in {@link KeplerianOrbit Keplerian parameters}. */
  550.     KEPLERIAN {

  551.         /** {@inheritDoc} */
  552.         @Override
  553.         public KeplerianOrbit convertType(final Orbit orbit) {
  554.             return (orbit.getType() == this) ? (KeplerianOrbit) orbit : new KeplerianOrbit(orbit);
  555.         }

  556.         /** {@inheritDoc} */
  557.         @Override
  558.         public void mapOrbitToArray(final Orbit orbit, final PositionAngle type,
  559.                                     final double[] stateVector, final double[] stateVectorDot) {

  560.             final KeplerianOrbit keplerianOrbit =
  561.                 (KeplerianOrbit) OrbitType.KEPLERIAN.convertType(orbit);

  562.             stateVector[0] = keplerianOrbit.getA();
  563.             stateVector[1] = keplerianOrbit.getE();
  564.             stateVector[2] = keplerianOrbit.getI();
  565.             stateVector[3] = keplerianOrbit.getPerigeeArgument();
  566.             stateVector[4] = keplerianOrbit.getRightAscensionOfAscendingNode();
  567.             stateVector[5] = keplerianOrbit.getAnomaly(type);

  568.             if (stateVectorDot != null) {
  569.                 if (orbit.hasDerivatives()) {
  570.                     stateVectorDot[0] = keplerianOrbit.getADot();
  571.                     stateVectorDot[1] = keplerianOrbit.getEDot();
  572.                     stateVectorDot[2] = keplerianOrbit.getIDot();
  573.                     stateVectorDot[3] = keplerianOrbit.getPerigeeArgumentDot();
  574.                     stateVectorDot[4] = keplerianOrbit.getRightAscensionOfAscendingNodeDot();
  575.                     stateVectorDot[5] = keplerianOrbit.getAnomalyDot(type);
  576.                 } else {
  577.                     Arrays.fill(stateVectorDot, 0, 6, Double.NaN);
  578.                 }
  579.             }

  580.         }

  581.         /** {@inheritDoc} */
  582.         @Override
  583.         public KeplerianOrbit mapArrayToOrbit(final double[] stateVector, final double[] stateVectorDot, final PositionAngle 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 PositionAngle 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.                 if (orbit.hasDerivatives()) {
  620.                     stateVectorDot[0] = keplerianOrbit.getADot();
  621.                     stateVectorDot[1] = keplerianOrbit.getEDot();
  622.                     stateVectorDot[2] = keplerianOrbit.getIDot();
  623.                     stateVectorDot[3] = keplerianOrbit.getPerigeeArgumentDot();
  624.                     stateVectorDot[4] = keplerianOrbit.getRightAscensionOfAscendingNodeDot();
  625.                     stateVectorDot[5] = keplerianOrbit.getAnomalyDot(type);
  626.                 } else {
  627.                     Arrays.fill(stateVectorDot, 0, 6, orbit.getDate().getField().getZero().add(Double.NaN));
  628.                 }
  629.             }

  630.         }

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

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

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

  673.             // convert input to proper type
  674.             final KeplerianOrbit kO = convertType(orbit);
  675.             final KeplerianOrbit kR = convertType(reference);

  676.             // perform normalization
  677.             if (kO.hasDerivatives()) {
  678.                 return new KeplerianOrbit(kO.getA(),
  679.                                           kO.getE(),
  680.                                           kO.getI(),
  681.                                           MathUtils.normalizeAngle(kO.getPerigeeArgument(), kR.getPerigeeArgument()),
  682.                                           MathUtils.normalizeAngle(kO.getRightAscensionOfAscendingNode(), kR.getRightAscensionOfAscendingNode()),
  683.                                           MathUtils.normalizeAngle(kO.getTrueAnomaly(), kR.getTrueAnomaly()),
  684.                                           kO.getADot(),
  685.                                           kO.getEDot(),
  686.                                           kO.getIDot(),
  687.                                           kO.getPerigeeArgumentDot(),
  688.                                           kO.getRightAscensionOfAscendingNodeDot(),
  689.                                           kO.getTrueAnomalyDot(),
  690.                                           PositionAngle.TRUE,
  691.                                           kO.getFrame(),
  692.                                           kO.getDate(),
  693.                                           kO.getMu());
  694.             } else {
  695.                 return new KeplerianOrbit(kO.getA(),
  696.                                           kO.getE(),
  697.                                           kO.getI(),
  698.                                           MathUtils.normalizeAngle(kO.getPerigeeArgument(), kR.getPerigeeArgument()),
  699.                                           MathUtils.normalizeAngle(kO.getRightAscensionOfAscendingNode(), kR.getRightAscensionOfAscendingNode()),
  700.                                           MathUtils.normalizeAngle(kO.getTrueAnomaly(), kR.getTrueAnomaly()),
  701.                                           PositionAngle.TRUE,
  702.                                           kO.getFrame(),
  703.                                           kO.getDate(),
  704.                                           kO.getMu());
  705.             }

  706.         }

  707.         /** {@inheritDoc} */
  708.         @Override
  709.         public <T extends CalculusFieldElement<T>> FieldKeplerianOrbit<T> normalize(final FieldOrbit<T> orbit, final FieldOrbit<T> reference) {

  710.             // convert input to proper type
  711.             final FieldKeplerianOrbit<T> kO = convertType(orbit);
  712.             final FieldKeplerianOrbit<T> kR = convertType(reference);

  713.             // perform normalization
  714.             if (kO.hasDerivatives()) {
  715.                 return new FieldKeplerianOrbit<>(kO.getA(),
  716.                                                  kO.getE(),
  717.                                                  kO.getI(),
  718.                                                  MathUtils.normalizeAngle(kO.getPerigeeArgument(), kR.getPerigeeArgument()),
  719.                                                  MathUtils.normalizeAngle(kO.getRightAscensionOfAscendingNode(), kR.getRightAscensionOfAscendingNode()),
  720.                                                  MathUtils.normalizeAngle(kO.getTrueAnomaly(), kR.getTrueAnomaly()),
  721.                                                  kO.getADot(),
  722.                                                  kO.getEDot(),
  723.                                                  kO.getIDot(),
  724.                                                  kO.getPerigeeArgumentDot(),
  725.                                                  kO.getRightAscensionOfAscendingNodeDot(),
  726.                                                  kO.getTrueAnomalyDot(),
  727.                                                  PositionAngle.TRUE,
  728.                                                  kO.getFrame(),
  729.                                                  kO.getDate(),
  730.                                                  kO.getMu());
  731.             } else {
  732.                 return new FieldKeplerianOrbit<>(kO.getA(),
  733.                                                  kO.getE(),
  734.                                                  kO.getI(),
  735.                                                  MathUtils.normalizeAngle(kO.getPerigeeArgument(), kR.getPerigeeArgument()),
  736.                                                  MathUtils.normalizeAngle(kO.getRightAscensionOfAscendingNode(), kR.getRightAscensionOfAscendingNode()),
  737.                                                  MathUtils.normalizeAngle(kO.getTrueAnomaly(), kR.getTrueAnomaly()),
  738.                                                  PositionAngle.TRUE,
  739.                                                  kO.getFrame(),
  740.                                                  kO.getDate(),
  741.                                                  kO.getMu());
  742.             }

  743.         }

  744.     };

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

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

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

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

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

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

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

  759.     /** Name for eccentricity. */
  760.     public static final String ECC   = "e";

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

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

  765.     /** Name for inclination. */
  766.     public static final String INC   = "i";

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

  887.     /** Get parameters drivers initialized from a reference orbit.
  888.      * @param dP user specified position error
  889.      * @param orbit reference orbit
  890.      * @param type type of the angle
  891.      * @return parameters drivers initialized from reference orbit
  892.      */
  893.     public abstract ParameterDriversList getDrivers(double dP, Orbit orbit,
  894.                                                     PositionAngle type);

  895.     /** Normalize one orbit with respect to a reference one.
  896.      * <p>
  897.      * Given a, angular component ζ of an orbit and the corresponding
  898.      * angular component ζᵣ in the reference orbit, the angular component
  899.      * ζₙ of the normalized orbit will be ζₙ = ζ + 2kπ
  900.      * where k is chosen such that ζᵣ - π ≤ ζₙ ≤ ζᵣ + π. This is intended
  901.      * to avoid too large discontinuities and is particularly useful
  902.      * for normalizing the orbit after an impulsive maneuver with respect
  903.      * to the reference picked up before the maneuver.
  904.      * </p>
  905.      * @param <T> CalculusFieldElement used
  906.      * @param orbit orbit to normalize
  907.      * @param reference reference orbit
  908.      * @return normalized orbit (the type is guaranteed to match {@link OrbitType})
  909.      * @since 11.1
  910.      */
  911.     public abstract <T extends CalculusFieldElement<T>> FieldOrbit<T> normalize(FieldOrbit<T> orbit, FieldOrbit<T> reference);

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

  928.     /** Compute scaling factor for parameters drivers.
  929.      * <p>
  930.      * The scales are estimated from partial derivatives properties of orbits,
  931.      * starting from a scalar position error specified by the user.
  932.      * Considering the energy conservation equation V = sqrt(mu (2/r - 1/a)),
  933.      * we get at constant energy (i.e. on a Keplerian trajectory):
  934.      * <pre>
  935.      * V r² |dV| = mu |dr|
  936.      * </pre>
  937.      * <p> So we deduce a scalar velocity error consistent with the position error.
  938.      * From here, we apply orbits Jacobians matrices to get consistent scales
  939.      * on orbital parameters.
  940.      *
  941.      * @param dP user specified position error
  942.      * @param orbit reference orbit
  943.      * @return scaling factor array
  944.      */
  945.     protected double[] scale(final double dP, final Orbit orbit) {

  946.         // estimate the scalar velocity error
  947.         final PVCoordinates pv = orbit.getPVCoordinates();
  948.         final double r2 = pv.getPosition().getNormSq();
  949.         final double v  = pv.getVelocity().getNorm();
  950.         final double dV = orbit.getMu() * dP / (v * r2);

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

  952.         // convert the orbit to the desired type
  953.         final double[][] jacobian = new double[6][6];
  954.         final Orbit converted = convertType(orbit);
  955.         converted.getJacobianWrtCartesian(PositionAngle.TRUE, jacobian);

  956.         for (int i = 0; i < 6; ++i) {
  957.             final double[] row = jacobian[i];
  958.             scale[i] = FastMath.abs(row[0]) * dP +
  959.                        FastMath.abs(row[1]) * dP +
  960.                        FastMath.abs(row[2]) * dP +
  961.                        FastMath.abs(row[3]) * dV +
  962.                        FastMath.abs(row[4]) * dV +
  963.                        FastMath.abs(row[5]) * dV;
  964.             if (Double.isNaN(scale[i])) {
  965.                 throw new OrekitException(OrekitMessages.SINGULAR_JACOBIAN_FOR_ORBIT_TYPE, this);
  966.             }
  967.         }

  968.         return scale;

  969.     }

  970. }