OrbitType.java

  1. /* Copyright 2002-2020 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.RealFieldElement;
  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.orekit.errors.OrekitException;
  24. import org.orekit.errors.OrekitMessages;
  25. import org.orekit.frames.Frame;
  26. import org.orekit.time.AbsoluteDate;
  27. import org.orekit.time.FieldAbsoluteDate;
  28. import org.orekit.utils.FieldPVCoordinates;
  29. import org.orekit.utils.PVCoordinates;
  30. import org.orekit.utils.ParameterDriver;
  31. import org.orekit.utils.ParameterDriversList;
  32. import org.orekit.utils.TimeStampedFieldPVCoordinates;

  33. /** Enumerate for {@link Orbit orbital} parameters types.
  34.  */
  35. public enum OrbitType {

  36.     /** Type for propagation in {@link CartesianOrbit Cartesian parameters}. */
  37.     CARTESIAN {

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

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

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

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

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

  65.         }

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

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

  81.         }

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

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

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

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

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

  111.         }

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

  130.         }

  131.         /** {@inheritDoc} */
  132.         @Override
  133.         public ParameterDriversList getDrivers(final double dP, final Orbit orbit, final PositionAngle type) {
  134.             final ParameterDriversList drivers = new ParameterDriversList();
  135.             final double[] array = new double[6];
  136.             mapOrbitToArray(orbit, type, array, null);
  137.             final double[] scale = scale(dP, orbit);
  138.             drivers.add(new ParameterDriver(POS_X, array[0], scale[0], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  139.             drivers.add(new ParameterDriver(POS_Y, array[1], scale[1], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  140.             drivers.add(new ParameterDriver(POS_Z, array[2], scale[2], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  141.             drivers.add(new ParameterDriver(VEL_X, array[3], scale[3], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  142.             drivers.add(new ParameterDriver(VEL_Y, array[4], scale[4], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  143.             drivers.add(new ParameterDriver(VEL_Z, array[5], scale[5], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  144.             return drivers;
  145.         }

  146.     },

  147.     /** Type for propagation in {@link CircularOrbit circular parameters}. */
  148.     CIRCULAR {

  149.         /** {@inheritDoc} */
  150.         @Override
  151.         public CircularOrbit convertType(final Orbit orbit) {
  152.             return (orbit.getType() == this) ? (CircularOrbit) orbit : new CircularOrbit(orbit);
  153.         }

  154.         /** {@inheritDoc} */
  155.         @Override
  156.         public void mapOrbitToArray(final Orbit orbit, final PositionAngle type,
  157.                                     final double[] stateVector, final double[] stateVectorDot) {

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

  159.             stateVector[0] = circularOrbit.getA();
  160.             stateVector[1] = circularOrbit.getCircularEx();
  161.             stateVector[2] = circularOrbit.getCircularEy();
  162.             stateVector[3] = circularOrbit.getI();
  163.             stateVector[4] = circularOrbit.getRightAscensionOfAscendingNode();
  164.             stateVector[5] = circularOrbit.getAlpha(type);

  165.             if (stateVectorDot != null) {
  166.                 if (orbit.hasDerivatives()) {
  167.                     stateVectorDot[0] = circularOrbit.getADot();
  168.                     stateVectorDot[1] = circularOrbit.getCircularExDot();
  169.                     stateVectorDot[2] = circularOrbit.getCircularEyDot();
  170.                     stateVectorDot[3] = circularOrbit.getIDot();
  171.                     stateVectorDot[4] = circularOrbit.getRightAscensionOfAscendingNodeDot();
  172.                     stateVectorDot[5] = circularOrbit.getAlphaDot(type);
  173.                 } else {
  174.                     Arrays.fill(stateVectorDot, 0, 6, Double.NaN);
  175.                 }
  176.             }

  177.         }

  178.         /** {@inheritDoc} */
  179.         @Override
  180.         public CircularOrbit mapArrayToOrbit(final double[] stateVector, final double[] stateVectorDot, final PositionAngle type,
  181.                                              final AbsoluteDate date, final double mu, final Frame frame) {
  182.             if (stateVectorDot == null) {
  183.                 // we don't have orbit derivatives
  184.                 return new CircularOrbit(stateVector[0], stateVector[1], stateVector[2],
  185.                                          stateVector[3], stateVector[4], stateVector[5],
  186.                                          type, frame, date, mu);
  187.             } else {
  188.                 // we have orbit derivatives
  189.                 return new CircularOrbit(stateVector[0],    stateVector[1],    stateVector[2],
  190.                                          stateVector[3],    stateVector[4],    stateVector[5],
  191.                                          stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  192.                                          stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  193.                                          type, frame, date, mu);
  194.             }
  195.         }

  196.         /** {@inheritDoc} */
  197.         @Override
  198.         public <T extends RealFieldElement<T>> FieldCircularOrbit<T> convertType(final FieldOrbit<T> orbit) {
  199.             return (orbit.getType() == this) ? (FieldCircularOrbit<T>) orbit : new FieldCircularOrbit<>(orbit);
  200.         }

  201.         /** {@inheritDoc} */
  202.         @Override
  203.         public <T extends RealFieldElement<T>> void mapOrbitToArray(final FieldOrbit<T> orbit,
  204.                                                                     final PositionAngle type,
  205.                                                                     final T[] stateVector,
  206.                                                                     final T[] stateVectorDot) {

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

  208.             stateVector[0] = circularOrbit.getA();
  209.             stateVector[1] = circularOrbit.getCircularEx();
  210.             stateVector[2] = circularOrbit.getCircularEy();
  211.             stateVector[3] = circularOrbit.getI();
  212.             stateVector[4] = circularOrbit.getRightAscensionOfAscendingNode();
  213.             stateVector[5] = circularOrbit.getAlpha(type);

  214.             if (stateVectorDot != null) {
  215.                 if (orbit.hasDerivatives()) {
  216.                     stateVectorDot[0] = circularOrbit.getADot();
  217.                     stateVectorDot[1] = circularOrbit.getCircularExDot();
  218.                     stateVectorDot[2] = circularOrbit.getCircularEyDot();
  219.                     stateVectorDot[3] = circularOrbit.getIDot();
  220.                     stateVectorDot[4] = circularOrbit.getRightAscensionOfAscendingNodeDot();
  221.                     stateVectorDot[5] = circularOrbit.getAlphaDot(type);
  222.                 } else {
  223.                     Arrays.fill(stateVectorDot, 0, 6, orbit.getDate().getField().getZero().add(Double.NaN));
  224.                 }
  225.             }

  226.         }

  227.         /** {@inheritDoc} */
  228.         @Override
  229.         public <T extends RealFieldElement<T>> FieldCircularOrbit<T> mapArrayToOrbit(final T[] stateVector,
  230.                                                                                      final T[] stateVectorDot, final PositionAngle type,
  231.                                                                                      final FieldAbsoluteDate<T> date,
  232.                                                                                      final T mu, final Frame frame) {
  233.             if (stateVectorDot == null) {
  234.                 // we don't have orbit derivatives
  235.                 return new FieldCircularOrbit<>(stateVector[0], stateVector[1], stateVector[2],
  236.                                                 stateVector[3], stateVector[4], stateVector[5],
  237.                                                 type, frame, date, mu);
  238.             } else {
  239.                 // we have orbit derivatives
  240.                 return new FieldCircularOrbit<>(stateVector[0],    stateVector[1],    stateVector[2],
  241.                                                 stateVector[3],    stateVector[4],    stateVector[5],
  242.                                                 stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  243.                                                 stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  244.                                                 type, frame, date, mu);
  245.             }
  246.         }

  247.         /** {@inheritDoc} */
  248.         @Override
  249.         public ParameterDriversList getDrivers(final double dP, final Orbit orbit, final PositionAngle type) {
  250.             final ParameterDriversList drivers = new ParameterDriversList();
  251.             final double[] array = new double[6];
  252.             mapOrbitToArray(orbit, type, array, null);
  253.             final double[] scale = scale(dP, orbit);
  254.             final String name = type == PositionAngle.MEAN ?
  255.                                     MEAN_LAT_ARG :
  256.                                     type == PositionAngle.ECCENTRIC ? ECC_LAT_ARG : TRUE_LAT_ARG;
  257.             drivers.add(new ParameterDriver(A,    array[0], scale[0],  0.0, Double.POSITIVE_INFINITY));
  258.             drivers.add(new ParameterDriver(E_X,  array[1], scale[1], -1.0, 1.0));
  259.             drivers.add(new ParameterDriver(E_Y,  array[2], scale[2], -1.0, 1.0));
  260.             drivers.add(new ParameterDriver(INC,  array[3], scale[3],  0.0, FastMath.PI));
  261.             drivers.add(new ParameterDriver(RAAN, array[4], scale[4], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  262.             drivers.add(new ParameterDriver(name, array[5], scale[5], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  263.             return drivers;
  264.         }

  265.     },

  266.     /** Type for propagation in {@link EquinoctialOrbit equinoctial parameters}. */
  267.     EQUINOCTIAL {

  268.         /** {@inheritDoc} */
  269.         @Override
  270.         public EquinoctialOrbit convertType(final Orbit orbit) {
  271.             return (orbit.getType() == this) ? (EquinoctialOrbit) orbit : new EquinoctialOrbit(orbit);
  272.         }

  273.         /** {@inheritDoc} */
  274.         @Override
  275.        public void mapOrbitToArray(final Orbit orbit, final PositionAngle type,
  276.                                    final double[] stateVector, final double[] stateVectorDot) {

  277.             final EquinoctialOrbit equinoctialOrbit =
  278.                 (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(orbit);

  279.             stateVector[0] = equinoctialOrbit.getA();
  280.             stateVector[1] = equinoctialOrbit.getEquinoctialEx();
  281.             stateVector[2] = equinoctialOrbit.getEquinoctialEy();
  282.             stateVector[3] = equinoctialOrbit.getHx();
  283.             stateVector[4] = equinoctialOrbit.getHy();
  284.             stateVector[5] = equinoctialOrbit.getL(type);

  285.             if (stateVectorDot != null) {
  286.                 if (orbit.hasDerivatives()) {
  287.                     stateVectorDot[0] = equinoctialOrbit.getADot();
  288.                     stateVectorDot[1] = equinoctialOrbit.getEquinoctialExDot();
  289.                     stateVectorDot[2] = equinoctialOrbit.getEquinoctialEyDot();
  290.                     stateVectorDot[3] = equinoctialOrbit.getHxDot();
  291.                     stateVectorDot[4] = equinoctialOrbit.getHyDot();
  292.                     stateVectorDot[5] = equinoctialOrbit.getLDot(type);
  293.                 } else {
  294.                     Arrays.fill(stateVectorDot, 0, 6, Double.NaN);
  295.                 }
  296.             }

  297.         }

  298.         /** {@inheritDoc} */
  299.         @Override
  300.         public EquinoctialOrbit mapArrayToOrbit(final double[] stateVector, final double[] stateVectorDot, final PositionAngle type,
  301.                                                 final AbsoluteDate date, final double mu, final Frame frame) {
  302.             if (stateVectorDot == null) {
  303.                 // we don't have orbit derivatives
  304.                 return new EquinoctialOrbit(stateVector[0], stateVector[1], stateVector[2],
  305.                                             stateVector[3], stateVector[4], stateVector[5],
  306.                                             type, frame, date, mu);
  307.             } else {
  308.                 // we have orbit derivatives
  309.                 return new EquinoctialOrbit(stateVector[0],    stateVector[1],    stateVector[2],
  310.                                             stateVector[3],    stateVector[4],    stateVector[5],
  311.                                             stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  312.                                             stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  313.                                             type, frame, date, mu);
  314.             }
  315.         }

  316.         /** {@inheritDoc} */
  317.         @Override
  318.         public <T extends RealFieldElement<T>> FieldEquinoctialOrbit<T> convertType(final FieldOrbit<T> orbit) {
  319.             return (orbit.getType() == this) ? (FieldEquinoctialOrbit<T>) orbit : new FieldEquinoctialOrbit<>(orbit);
  320.         }

  321.         /** {@inheritDoc} */
  322.         @Override
  323.         public <T extends RealFieldElement<T>> void mapOrbitToArray(final FieldOrbit<T> orbit,
  324.                                                                     final PositionAngle type,
  325.                                                                     final T[] stateVector,
  326.                                                                     final T[] stateVectorDot) {

  327.             final FieldEquinoctialOrbit<T> equinoctialOrbit =
  328.                 (FieldEquinoctialOrbit<T>) OrbitType.EQUINOCTIAL.convertType(orbit);

  329.             stateVector[0] = equinoctialOrbit.getA();
  330.             stateVector[1] = equinoctialOrbit.getEquinoctialEx();
  331.             stateVector[2] = equinoctialOrbit.getEquinoctialEy();
  332.             stateVector[3] = equinoctialOrbit.getHx();
  333.             stateVector[4] = equinoctialOrbit.getHy();
  334.             stateVector[5] = equinoctialOrbit.getL(type);

  335.             if (stateVectorDot != null) {
  336.                 if (orbit.hasDerivatives()) {
  337.                     stateVectorDot[0] = equinoctialOrbit.getADot();
  338.                     stateVectorDot[1] = equinoctialOrbit.getEquinoctialExDot();
  339.                     stateVectorDot[2] = equinoctialOrbit.getEquinoctialEyDot();
  340.                     stateVectorDot[3] = equinoctialOrbit.getHxDot();
  341.                     stateVectorDot[4] = equinoctialOrbit.getHyDot();
  342.                     stateVectorDot[5] = equinoctialOrbit.getLDot(type);
  343.                 } else {
  344.                     Arrays.fill(stateVectorDot, 0, 6, orbit.getDate().getField().getZero().add(Double.NaN));
  345.                 }
  346.             }

  347.         }

  348.         /** {@inheritDoc} */
  349.         @Override
  350.         public <T extends RealFieldElement<T>> FieldEquinoctialOrbit<T> mapArrayToOrbit(final T[] stateVector,
  351.                                                                                         final T[] stateVectorDot,
  352.                                                                                         final PositionAngle type,
  353.                                                                                         final FieldAbsoluteDate<T> date,
  354.                                                                                         final T mu, final Frame frame) {
  355.             if (stateVectorDot == null) {
  356.                 // we don't have orbit derivatives
  357.                 return new FieldEquinoctialOrbit<>(stateVector[0], stateVector[1], stateVector[2],
  358.                                                    stateVector[3], stateVector[4], stateVector[5],
  359.                                                    type, frame, date, mu);
  360.             } else {
  361.                 // we have orbit derivatives
  362.                 return new FieldEquinoctialOrbit<>(stateVector[0],    stateVector[1],    stateVector[2],
  363.                                                    stateVector[3],    stateVector[4],    stateVector[5],
  364.                                                    stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  365.                                                    stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  366.                                                    type, frame, date, mu);
  367.             }
  368.         }

  369.         /** {@inheritDoc} */
  370.         @Override
  371.         public ParameterDriversList getDrivers(final double dP, final Orbit orbit, final PositionAngle type) {
  372.             final ParameterDriversList drivers = new ParameterDriversList();
  373.             final double[] array = new double[6];
  374.             mapOrbitToArray(orbit, type, array, null);
  375.             final double[] scale = scale(dP, orbit);
  376.             final String name = type == PositionAngle.MEAN ?
  377.                                     MEAN_LON_ARG :
  378.                                     type == PositionAngle.ECCENTRIC ? ECC_LON_ARG : TRUE_LON_ARG;
  379.             drivers.add(new ParameterDriver(A,    array[0], scale[0],  0.0, Double.POSITIVE_INFINITY));
  380.             drivers.add(new ParameterDriver(E_X,  array[1], scale[1], -1.0, 1.0));
  381.             drivers.add(new ParameterDriver(E_Y,  array[2], scale[2], -1.0, 1.0));
  382.             drivers.add(new ParameterDriver(H_X,  array[3], scale[3], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  383.             drivers.add(new ParameterDriver(H_Y,  array[4], scale[4], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  384.             drivers.add(new ParameterDriver(name, array[5], scale[5], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  385.             return drivers;
  386.         }


  387.     },

  388.     /** Type for propagation in {@link KeplerianOrbit Keplerian parameters}. */
  389.     KEPLERIAN {

  390.         /** {@inheritDoc} */
  391.         @Override
  392.         public KeplerianOrbit convertType(final Orbit orbit) {
  393.             return (orbit.getType() == this) ? (KeplerianOrbit) orbit : new KeplerianOrbit(orbit);
  394.         }

  395.         /** {@inheritDoc} */
  396.         @Override
  397.         public void mapOrbitToArray(final Orbit orbit, final PositionAngle type,
  398.                                     final double[] stateVector, final double[] stateVectorDot) {

  399.             final KeplerianOrbit keplerianOrbit =
  400.                 (KeplerianOrbit) OrbitType.KEPLERIAN.convertType(orbit);

  401.             stateVector[0] = keplerianOrbit.getA();
  402.             stateVector[1] = keplerianOrbit.getE();
  403.             stateVector[2] = keplerianOrbit.getI();
  404.             stateVector[3] = keplerianOrbit.getPerigeeArgument();
  405.             stateVector[4] = keplerianOrbit.getRightAscensionOfAscendingNode();
  406.             stateVector[5] = keplerianOrbit.getAnomaly(type);

  407.             if (stateVectorDot != null) {
  408.                 if (orbit.hasDerivatives()) {
  409.                     stateVectorDot[0] = keplerianOrbit.getADot();
  410.                     stateVectorDot[1] = keplerianOrbit.getEDot();
  411.                     stateVectorDot[2] = keplerianOrbit.getIDot();
  412.                     stateVectorDot[3] = keplerianOrbit.getPerigeeArgumentDot();
  413.                     stateVectorDot[4] = keplerianOrbit.getRightAscensionOfAscendingNodeDot();
  414.                     stateVectorDot[5] = keplerianOrbit.getAnomalyDot(type);
  415.                 } else {
  416.                     Arrays.fill(stateVectorDot, 0, 6, Double.NaN);
  417.                 }
  418.             }

  419.         }

  420.         /** {@inheritDoc} */
  421.         @Override
  422.         public KeplerianOrbit mapArrayToOrbit(final double[] stateVector, final double[] stateVectorDot, final PositionAngle type,
  423.                                               final AbsoluteDate date, final double mu, final Frame frame) {
  424.             if (stateVectorDot == null) {
  425.                 // we don't have orbit derivatives
  426.                 return new KeplerianOrbit(stateVector[0], stateVector[1], stateVector[2],
  427.                                           stateVector[3], stateVector[4], stateVector[5],
  428.                                           type, frame, date, mu);
  429.             } else {
  430.                 // we have orbit derivatives
  431.                 return new KeplerianOrbit(stateVector[0],    stateVector[1],    stateVector[2],
  432.                                           stateVector[3],    stateVector[4],    stateVector[5],
  433.                                           stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  434.                                           stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  435.                                           type, frame, date, mu);
  436.             }
  437.         }

  438.         /** {@inheritDoc} */
  439.         @Override
  440.         public <T extends RealFieldElement<T>> FieldKeplerianOrbit<T> convertType(final FieldOrbit<T> orbit) {
  441.             return (orbit.getType() == this) ? (FieldKeplerianOrbit<T>) orbit : new FieldKeplerianOrbit<>(orbit);
  442.         }

  443.         /** {@inheritDoc} */
  444.         @Override
  445.         public <T extends RealFieldElement<T>> void mapOrbitToArray(final FieldOrbit<T> orbit,
  446.                                                                     final PositionAngle type,
  447.                                                                     final T[] stateVector,
  448.                                                                     final T[] stateVectorDot) {
  449.             final FieldKeplerianOrbit<T> keplerianOrbit =
  450.                             (FieldKeplerianOrbit<T>) OrbitType.KEPLERIAN.convertType(orbit);

  451.             stateVector[0] = keplerianOrbit.getA();
  452.             stateVector[1] = keplerianOrbit.getE();
  453.             stateVector[2] = keplerianOrbit.getI();
  454.             stateVector[3] = keplerianOrbit.getPerigeeArgument();
  455.             stateVector[4] = keplerianOrbit.getRightAscensionOfAscendingNode();
  456.             stateVector[5] = keplerianOrbit.getAnomaly(type);

  457.             if (stateVectorDot != null) {
  458.                 if (orbit.hasDerivatives()) {
  459.                     stateVectorDot[0] = keplerianOrbit.getADot();
  460.                     stateVectorDot[1] = keplerianOrbit.getEDot();
  461.                     stateVectorDot[2] = keplerianOrbit.getIDot();
  462.                     stateVectorDot[3] = keplerianOrbit.getPerigeeArgumentDot();
  463.                     stateVectorDot[4] = keplerianOrbit.getRightAscensionOfAscendingNodeDot();
  464.                     stateVectorDot[5] = keplerianOrbit.getAnomalyDot(type);
  465.                 } else {
  466.                     Arrays.fill(stateVectorDot, 0, 6, orbit.getDate().getField().getZero().add(Double.NaN));
  467.                 }
  468.             }

  469.         }

  470.         /** {@inheritDoc} */
  471.         @Override
  472.         public <T extends RealFieldElement<T>> FieldKeplerianOrbit<T> mapArrayToOrbit(final T[] stateVector,
  473.                                                                                       final T[] stateVectorDot,
  474.                                                                                       final PositionAngle type,
  475.                                                                                       final FieldAbsoluteDate<T> date,
  476.                                                                                       final T mu, final Frame frame) {
  477.             if (stateVectorDot == null) {
  478.                 // we don't have orbit derivatives
  479.                 return new FieldKeplerianOrbit<>(stateVector[0], stateVector[1], stateVector[2],
  480.                                                  stateVector[3], stateVector[4], stateVector[5],
  481.                                                  type, frame, date, mu);
  482.             } else {
  483.                 // we have orbit derivatives
  484.                 return new FieldKeplerianOrbit<>(stateVector[0],    stateVector[1],    stateVector[2],
  485.                                                  stateVector[3],    stateVector[4],    stateVector[5],
  486.                                                  stateVectorDot[0], stateVectorDot[1], stateVectorDot[2],
  487.                                                  stateVectorDot[3], stateVectorDot[4], stateVectorDot[5],
  488.                                                  type, frame, date, mu);
  489.             }
  490.         }

  491.         /** {@inheritDoc} */
  492.         @Override
  493.         public ParameterDriversList getDrivers(final double dP, final Orbit orbit, final PositionAngle type) {
  494.             final ParameterDriversList drivers = new ParameterDriversList();
  495.             final double[] array = new double[6];
  496.             mapOrbitToArray(orbit, type, array, null);
  497.             final double[] scale = scale(dP, orbit);
  498.             final String name = type == PositionAngle.MEAN ?
  499.                                     MEAN_ANOM :
  500.                                     type == PositionAngle.ECCENTRIC ? ECC_ANOM : TRUE_ANOM;
  501.             drivers.add(new ParameterDriver(A,    array[0], scale[0],  0.0, Double.POSITIVE_INFINITY));
  502.             drivers.add(new ParameterDriver(ECC,  array[1], scale[1],  0.0, 1.0));
  503.             drivers.add(new ParameterDriver(INC,  array[2], scale[2],  0.0, FastMath.PI));
  504.             drivers.add(new ParameterDriver(PA,   array[3], scale[3], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  505.             drivers.add(new ParameterDriver(RAAN, array[4], scale[4], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  506.             drivers.add(new ParameterDriver(name, array[5], scale[5], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
  507.             return drivers;
  508.         }

  509.     };

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

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

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

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

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

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

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

  524.     /** Name for eccentricity. */
  525.     public static final String ECC   = "e";

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

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

  530.     /** Name for inclination. */
  531.     public static final String INC   = "i";

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

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

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

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

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

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

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

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

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

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

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

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

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

  558.     /** Convert an orbit to the instance type.
  559.      * <p>
  560.      * The returned orbit is the specified instance itself if its type already matches,
  561.      * otherwise, a new orbit of the proper type created
  562.      * </p>
  563.      * @param orbit orbit to convert
  564.      * @return converted orbit with type guaranteed to match (so it can be cast safely)
  565.      */
  566.     public abstract Orbit convertType(Orbit orbit);

  567.     /** Convert orbit to state array.
  568.      * <p>
  569.      * Note that all implementations of this method <em>must</em> be consistent with the
  570.      * implementation of the {@link org.orekit.orbits.Orbit#getJacobianWrtCartesian(
  571.      * org.orekit.orbits.PositionAngle, double[][]) Orbit.getJacobianWrtCartesian}
  572.      * method for the corresponding orbit type in terms of parameters order and meaning.
  573.      * </p>
  574.      * @param orbit orbit to map
  575.      * @param type type of the angle
  576.      * @param stateVector flat array into which the state vector should be mapped
  577.      * (it can have more than 6 elements, extra elements are untouched)
  578.      * @param stateVectorDot flat array into which the state vector derivative should be mapped
  579.      * (it can be null if derivatives are not desired, and it can have more than 6 elements, extra elements are untouched)
  580.      */
  581.     public abstract void mapOrbitToArray(Orbit orbit, PositionAngle type, double[] stateVector, double[] stateVectorDot);

  582.      /** Convert state array to orbital parameters.
  583.      * <p>
  584.      * Note that all implementations of this method <em>must</em> be consistent with the
  585.      * implementation of the {@link org.orekit.orbits.Orbit#getJacobianWrtCartesian(
  586.      * org.orekit.orbits.PositionAngle, double[][]) Orbit.getJacobianWrtCartesian}
  587.      * method for the corresponding orbit type in terms of parameters order and meaning.
  588.      * </p>
  589.      * @param array state as a flat array
  590.      * (it can have more than 6 elements, extra elements are ignored)
  591.      * @param arrayDot state derivative as a flat array
  592.      * (it can be null, in which case Keplerian motion is assumed,
  593.      * and it can have more than 6 elements, extra elements are ignored)
  594.      * @param type type of the angle
  595.      * @param date integration date
  596.      * @param mu central attraction coefficient used for propagation (m³/s²)
  597.      * @param frame frame in which integration is performed
  598.      * @return orbit corresponding to the flat array as a space dynamics object
  599.      */
  600.     public abstract Orbit mapArrayToOrbit(double[] array, double arrayDot[], PositionAngle type,
  601.                                           AbsoluteDate date, double mu, Frame frame);

  602.     /** Convert an orbit to the instance type.
  603.      * <p>
  604.      * The returned orbit is the specified instance itself if its type already matches,
  605.      * otherwise, a new orbit of the proper type created
  606.      * </p>
  607.      * @param <T> RealFieldElement used
  608.      * @param orbit orbit to convert
  609.      * @return converted orbit with type guaranteed to match (so it can be cast safely)
  610.      */
  611.     public abstract <T extends RealFieldElement<T>> FieldOrbit<T> convertType(FieldOrbit<T> orbit);

  612.     /** Convert orbit to state array.
  613.      * <p>
  614.      * Note that all implementations of this method <em>must</em> be consistent with the
  615.      * implementation of the {@link org.orekit.orbits.Orbit#getJacobianWrtCartesian(
  616.      * org.orekit.orbits.PositionAngle, double[][]) Orbit.getJacobianWrtCartesian}
  617.      * method for the corresponding orbit type in terms of parameters order and meaning.
  618.      * </p>
  619.      * @param <T> RealFieldElement used
  620.      * @param orbit orbit to map
  621.      * @param type type of the angle
  622.      * @param stateVector flat array into which the state vector should be mapped
  623.      * (it can have more than 6 elements, extra elements are untouched)
  624.      * @param stateVectorDot flat array into which the state vector derivative should be mapped
  625.      * (it can be null if derivatives are not desired, and it can have more than 6 elements, extra elements are untouched)
  626.      */
  627.     public abstract <T extends RealFieldElement<T>>void mapOrbitToArray(FieldOrbit<T> orbit, PositionAngle type,
  628.                                                                         T[] stateVector, T[] stateVectorDot);


  629.     /** Convert state array to orbital parameters.
  630.      * <p>
  631.      * Note that all implementations of this method <em>must</em> be consistent with the
  632.      * implementation of the {@link org.orekit.orbits.Orbit#getJacobianWrtCartesian(
  633.      * org.orekit.orbits.PositionAngle, double[][]) Orbit.getJacobianWrtCartesian}
  634.      * method for the corresponding orbit type in terms of parameters order and meaning.
  635.      * </p>
  636.      * @param <T> RealFieldElement used
  637.      * @param array state as a flat array
  638.      * (it can have more than 6 elements, extra elements are ignored)
  639.      * @param arrayDot state derivative as a flat array
  640.      * (it can be null, in which case Keplerian motion is assumed,
  641.      * @param type type of the angle
  642.      * @param date integration date
  643.      * @param mu central attraction coefficient used for propagation (m³/s²)
  644.      * @param frame frame in which integration is performed
  645.      * @return orbit corresponding to the flat array as a space dynamics object
  646.      */
  647.     public abstract <T extends RealFieldElement<T>> FieldOrbit<T> mapArrayToOrbit(T[] array,
  648.                                                                                   T[] arrayDot,
  649.                                                                                   PositionAngle type,
  650.                                                                                   FieldAbsoluteDate<T> date,
  651.                                                                                   T mu, Frame frame);

  652.     /** Get parameters drivers initialized from a reference orbit.
  653.      * @param dP user specified position error
  654.      * @param orbit reference orbit
  655.      * @param type type of the angle
  656.      * @return parameters drivers initialized from reference orbit
  657.      */
  658.     public abstract ParameterDriversList getDrivers(double dP, Orbit orbit,
  659.                                                     PositionAngle type);

  660.     /** Compute scaling factor for parameters drivers.
  661.      * <p>
  662.      * The scales are estimated from partial derivatives properties of orbits,
  663.      * starting from a scalar position error specified by the user.
  664.      * Considering the energy conservation equation V = sqrt(mu (2/r - 1/a)),
  665.      * we get at constant energy (i.e. on a Keplerian trajectory):
  666.      * <pre>
  667.      * V² r |dV| = mu |dr|
  668.      * </pre>
  669.      * <p> So we deduce a scalar velocity error consistent with the position error.
  670.      * From here, we apply orbits Jacobians matrices to get consistent scales
  671.      * on orbital parameters.
  672.      *
  673.      * @param dP user specified position error
  674.      * @param orbit reference orbit
  675.      * @return scaling factor array
  676.      */
  677.     protected double[] scale(final double dP, final Orbit orbit) {

  678.         // estimate the scalar velocity error
  679.         final PVCoordinates pv = orbit.getPVCoordinates();
  680.         final double r2 = pv.getPosition().getNormSq();
  681.         final double v  = pv.getVelocity().getNorm();
  682.         final double dV = orbit.getMu() * dP / (v * r2);

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

  684.         // convert the orbit to the desired type
  685.         final double[][] jacobian = new double[6][6];
  686.         final Orbit converted = convertType(orbit);
  687.         converted.getJacobianWrtCartesian(PositionAngle.TRUE, jacobian);

  688.         for (int i = 0; i < 6; ++i) {
  689.             final double[] row = jacobian[i];
  690.             scale[i] = FastMath.abs(row[0]) * dP +
  691.                        FastMath.abs(row[1]) * dP +
  692.                        FastMath.abs(row[2]) * dP +
  693.                        FastMath.abs(row[3]) * dV +
  694.                        FastMath.abs(row[4]) * dV +
  695.                        FastMath.abs(row[5]) * dV;
  696.             if (Double.isNaN(scale[i])) {
  697.                 throw new OrekitException(OrekitMessages.SINGULAR_JACOBIAN_FOR_ORBIT_TYPE, this);
  698.             }
  699.         }

  700.         return scale;

  701.     }

  702. }