OrbitType.java

  1. /* Copyright 2002-2018 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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 double 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.             throws OrekitException {
  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.     },

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

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

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

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

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

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

  178.         }

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

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

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

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

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

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

  227.         }

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

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

  267.     },

  268.     /** Type for propagation in {@link EquinoctialOrbit equinoctial parameters}. */
  269.     EQUINOCTIAL {

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

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

  279.             final EquinoctialOrbit equinoctialOrbit =
  280.                 (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(orbit);

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

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

  299.         }

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

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

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

  329.             final FieldEquinoctialOrbit<T> equinoctialOrbit =
  330.                 (FieldEquinoctialOrbit<T>) OrbitType.EQUINOCTIAL.convertType(orbit);

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

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

  349.         }

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

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


  390.     },

  391.     /** Type for propagation in {@link KeplerianOrbit Keplerian parameters}. */
  392.     KEPLERIAN {

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

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

  402.             final KeplerianOrbit keplerianOrbit =
  403.                 (KeplerianOrbit) OrbitType.KEPLERIAN.convertType(orbit);

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

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

  422.         }

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

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

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

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

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

  472.         }

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

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

  513.     };

  514.     /** Name for position along X. */
  515.     private static final String POS_X = "Px";

  516.     /** Name for position along Y. */
  517.     private static final String POS_Y = "Py";

  518.     /** Name for position along Z. */
  519.     private static final String POS_Z = "Pz";

  520.     /** Name for velocity along X. */
  521.     private static final String VEL_X = "Vx";

  522.     /** Name for velocity along Y. */
  523.     private static final String VEL_Y = "Vy";

  524.     /** Name for velocity along Z. */
  525.     private static final String VEL_Z = "Vz";

  526.     /** Name for semi major axis. */
  527.     private static final String A     = "a";

  528.     /** Name for eccentricity. */
  529.     private static final String ECC   = "e";

  530.     /** Name for eccentricity vector first component. */
  531.     private static final String E_X   = "ex";

  532.     /** Name for eccentricity vector second component. */
  533.     private static final String E_Y   = "ey";

  534.     /** Name for inclination. */
  535.     private static final String INC   = "i";

  536.     /** Name for inclination vector first component. */
  537.     private static final String H_X   = "hx";

  538.     /** Name for inclination vector second component . */
  539.     private static final String H_Y   = "hy";

  540.     /** Name for perigee argument. */
  541.     private static final String PA    = "ω";

  542.     /** Name for right ascension of ascending node. */
  543.     private static final String RAAN    = "Ω";

  544.     /** Name for mean anomaly. */
  545.     private static final String MEAN_ANOM = "M";

  546.     /** Name for eccentric anomaly. */
  547.     private static final String ECC_ANOM  = "E";

  548.     /** Name for mean anomaly. */
  549.     private static final String TRUE_ANOM = "v";

  550.     /** Name for mean argument of latitude. */
  551.     private static final String MEAN_LAT_ARG = "αM";

  552.     /** Name for eccentric argument of latitude. */
  553.     private static final String ECC_LAT_ARG  = "αE";

  554.     /** Name for mean argument of latitude. */
  555.     private static final String TRUE_LAT_ARG = "αv";

  556.     /** Name for mean argument of longitude. */
  557.     private static final String MEAN_LON_ARG = "λM";

  558.     /** Name for eccentric argument of longitude. */
  559.     private static final String ECC_LON_ARG  = "λE";

  560.     /** Name for mean argument of longitude. */
  561.     private static final String TRUE_LON_ARG = "λv";

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

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

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

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

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


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

  656.     /** Get parameters drivers initialized from a reference orbit.
  657.      * @param dP user specified position error
  658.      * @param orbit reference orbit
  659.      * @param type type of the angle
  660.      * @return parameters drivers initialized from reference orbit
  661.      * @exception OrekitException if Jacobian is singular
  662.      */
  663.     public abstract ParameterDriversList getDrivers(double dP, Orbit orbit,
  664.                                                     PositionAngle type)
  665.         throws OrekitException;

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

  686.         // estimate the scalar velocity error
  687.         final PVCoordinates pv = orbit.getPVCoordinates();
  688.         final double r2 = pv.getPosition().getNormSq();
  689.         final double v  = pv.getVelocity().getNorm();
  690.         final double dV = orbit.getMu() * dP / (v * r2);

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

  692.         // convert the orbit to the desired type
  693.         final double[][] jacobian = new double[6][6];
  694.         final Orbit converted = convertType(orbit);
  695.         converted.getJacobianWrtCartesian(PositionAngle.TRUE, jacobian);

  696.         for (int i = 0; i < 6; ++i) {
  697.             final double[] row = jacobian[i];
  698.             scale[i] = FastMath.abs(row[0]) * dP +
  699.                        FastMath.abs(row[1]) * dP +
  700.                        FastMath.abs(row[2]) * dP +
  701.                        FastMath.abs(row[3]) * dV +
  702.                        FastMath.abs(row[4]) * dV +
  703.                        FastMath.abs(row[5]) * dV;
  704.             if (Double.isNaN(scale[i])) {
  705.                 throw new OrekitException(OrekitMessages.SINGULAR_JACOBIAN_FOR_ORBIT_TYPE, this);
  706.             }
  707.         }

  708.         return scale;

  709.     }

  710. }