IntegratedEphemeris.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.propagation.integration;

  18. import java.io.NotSerializableException;
  19. import java.io.Serializable;
  20. import java.util.ArrayList;
  21. import java.util.Arrays;
  22. import java.util.HashMap;
  23. import java.util.List;
  24. import java.util.Map;

  25. import org.hipparchus.ode.DenseOutputModel;
  26. import org.hipparchus.ode.ODEStateAndDerivative;
  27. import org.orekit.errors.OrekitException;
  28. import org.orekit.errors.OrekitExceptionWrapper;
  29. import org.orekit.errors.OrekitInternalError;
  30. import org.orekit.errors.OrekitMessages;
  31. import org.orekit.frames.Frame;
  32. import org.orekit.orbits.Orbit;
  33. import org.orekit.propagation.AdditionalStateProvider;
  34. import org.orekit.propagation.BoundedPropagator;
  35. import org.orekit.propagation.SpacecraftState;
  36. import org.orekit.propagation.analytical.AbstractAnalyticalPropagator;
  37. import org.orekit.time.AbsoluteDate;
  38. import org.orekit.utils.TimeStampedPVCoordinates;

  39. /** This class stores sequentially generated orbital parameters for
  40.  * later retrieval.
  41.  *
  42.  * <p>
  43.  * Instances of this class are built and then must be fed with the results
  44.  * provided by {@link org.orekit.propagation.Propagator Propagator} objects
  45.  * configured in {@link org.orekit.propagation.Propagator#setEphemerisMode()
  46.  * ephemeris generation mode}. Once propagation is o, random access to any
  47.  * intermediate state of the orbit throughout the propagation range is possible.
  48.  * </p>
  49.  * <p>
  50.  * A typical use case is for numerically integrated orbits, which can be used by
  51.  * algorithms that need to wander around according to their own algorithm without
  52.  * cumbersome tight links with the integrator.
  53.  * </p>
  54.  * <p>
  55.  * Another use case is persistence, as this class is one of the few propagators
  56.  * to be serializable.
  57.  * </p>
  58.  * <p>
  59.  * As this class implements the {@link org.orekit.propagation.Propagator Propagator}
  60.  * interface, it can itself be used in batch mode to build another instance of the
  61.  * same type. This is however not recommended since it would be a waste of resources.
  62.  * </p>
  63.  * <p>
  64.  * Note that this class stores all intermediate states along with interpolation
  65.  * models, so it may be memory intensive.
  66.  * </p>
  67.  *
  68.  * @see org.orekit.propagation.numerical.NumericalPropagator
  69.  * @author Mathieu Rom&eacute;ro
  70.  * @author Luc Maisonobe
  71.  * @author V&eacute;ronique Pommier-Maurussane
  72.  */
  73. public class IntegratedEphemeris
  74.     extends AbstractAnalyticalPropagator implements BoundedPropagator, Serializable  {

  75.     /** Serializable UID. */
  76.     private static final long serialVersionUID = 20140213L;

  77.     /** Event detection requires evaluating the state slightly before / past an event. */
  78.     private static final double EXTRAPOLATION_TOLERANCE = 1.0;

  79.     /** Mapper between raw double components and spacecraft state. */
  80.     private final StateMapper mapper;

  81.     /** Output only the mean orbit.
  82.      * <p>
  83.      * This is used only in the case of semianalitical propagators where there is a clear separation between
  84.      * mean and short periodic elements. It is ignored by the Numerical propagator.
  85.      * </p>
  86.      */
  87.     private boolean meanOrbit;

  88.     /** Start date of the integration (can be min or max). */
  89.     private final AbsoluteDate startDate;

  90.     /** First date of the range. */
  91.     private final AbsoluteDate minDate;

  92.     /** Last date of the range. */
  93.     private final AbsoluteDate maxDate;

  94.     /** Underlying raw mathematical model. */
  95.     private DenseOutputModel model;

  96.     /** Unmanaged additional states that must be simply copied. */
  97.     private final Map<String, double[]> unmanaged;

  98.     /** Creates a new instance of IntegratedEphemeris.
  99.      * @param startDate Start date of the integration (can be minDate or maxDate)
  100.      * @param minDate first date of the range
  101.      * @param maxDate last date of the range
  102.      * @param mapper mapper between raw double components and spacecraft state
  103.      * @param meanOrbit output only the mean orbit
  104.      * @param model underlying raw mathematical model
  105.      * @param unmanaged unmanaged additional states that must be simply copied
  106.      * @param providers providers for pre-integrated states
  107.      * @param equations names of additional equations
  108.      * @exception OrekitException if several providers have the same name
  109.      */
  110.     public IntegratedEphemeris(final AbsoluteDate startDate,
  111.                                final AbsoluteDate minDate, final AbsoluteDate maxDate,
  112.                                final StateMapper mapper, final boolean meanOrbit,
  113.                                final DenseOutputModel model,
  114.                                final Map<String, double[]> unmanaged,
  115.                                final List<AdditionalStateProvider> providers,
  116.                                final String[] equations)
  117.         throws OrekitException {

  118.         super(mapper.getAttitudeProvider());

  119.         this.startDate = startDate;
  120.         this.minDate   = minDate;
  121.         this.maxDate   = maxDate;
  122.         this.mapper    = mapper;
  123.         this.meanOrbit = meanOrbit;
  124.         this.model     = model;
  125.         this.unmanaged = unmanaged;

  126.         // set up the pre-integrated providers
  127.         for (final AdditionalStateProvider provider : providers) {
  128.             addAdditionalStateProvider(provider);
  129.         }

  130.         // set up providers to map the final elements of the model array to additional states
  131.         for (int i = 0; i < equations.length; ++i) {
  132.             addAdditionalStateProvider(new LocalProvider(equations[i], i));
  133.         }

  134.     }

  135.     /** Interpolate the model at some date.
  136.      * @param date desired interpolation date
  137.      * @return state interpolated at date
  138.      * @exception OrekitException if specified date is outside
  139.      * of supported range
  140.      */
  141.     private ODEStateAndDerivative getInterpolatedState(final AbsoluteDate date)
  142.         throws OrekitException {

  143.         // compare using double precision instead of AbsoluteDate.compareTo(...)
  144.         // because time is expressed as a double when searching for events
  145.         if (date.compareTo(minDate.shiftedBy(-EXTRAPOLATION_TOLERANCE)) < 0 ||
  146.                 date.compareTo(maxDate.shiftedBy(EXTRAPOLATION_TOLERANCE)) > 0 ) {
  147.             // date is outside of supported range
  148.             throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE,
  149.                                            date, minDate, maxDate);
  150.         }

  151.         return model.getInterpolatedState(date.durationFrom(startDate));

  152.     }

  153.     /** {@inheritDoc} */
  154.     @Override
  155.     protected SpacecraftState basicPropagate(final AbsoluteDate date)
  156.         throws OrekitException {
  157.         try {
  158.             final ODEStateAndDerivative os = getInterpolatedState(date);
  159.             SpacecraftState state = mapper.mapArrayToState(mapper.mapDoubleToDate(os.getTime(), date),
  160.                                                            os.getPrimaryState(), os.getPrimaryDerivative(),
  161.                                                            meanOrbit);
  162.             for (Map.Entry<String, double[]> initial : unmanaged.entrySet()) {
  163.                 state = state.addAdditionalState(initial.getKey(), initial.getValue());
  164.             }
  165.             return state;
  166.         } catch (OrekitExceptionWrapper oew) {
  167.             throw oew.getException();
  168.         }
  169.     }

  170.     /** {@inheritDoc} */
  171.     protected Orbit propagateOrbit(final AbsoluteDate date)
  172.         throws OrekitException {
  173.         return basicPropagate(date).getOrbit();
  174.     }

  175.     /** {@inheritDoc} */
  176.     protected double getMass(final AbsoluteDate date) throws OrekitException {
  177.         return basicPropagate(date).getMass();
  178.     }

  179.     /** {@inheritDoc} */
  180.     public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame)
  181.         throws OrekitException {
  182.         return propagate(date).getPVCoordinates(frame);
  183.     }

  184.     /** Get the first date of the range.
  185.      * @return the first date of the range
  186.      */
  187.     public AbsoluteDate getMinDate() {
  188.         return minDate;
  189.     }

  190.     /** Get the last date of the range.
  191.      * @return the last date of the range
  192.      */
  193.     public AbsoluteDate getMaxDate() {
  194.         return maxDate;
  195.     }

  196.     @Override
  197.     public Frame getFrame() {
  198.         return this.mapper.getFrame();
  199.     }

  200.     /** {@inheritDoc} */
  201.     public void resetInitialState(final SpacecraftState state)
  202.         throws OrekitException {
  203.         throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
  204.     }

  205.     /** {@inheritDoc} */
  206.     protected void resetIntermediateState(final SpacecraftState state, final boolean forward)
  207.         throws OrekitException {
  208.         throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
  209.     }

  210.     /** {@inheritDoc} */
  211.     public SpacecraftState getInitialState() throws OrekitException {
  212.         return updateAdditionalStates(basicPropagate(getMinDate()));
  213.     }

  214.     /** Replace the instance with a data transfer object for serialization.
  215.      * @return data transfer object that will be serialized
  216.      * @exception NotSerializableException if the state mapper cannot be serialized (typically for DSST propagator)
  217.      */
  218.     private Object writeReplace() throws NotSerializableException {

  219.         // unmanaged additional states
  220.         final String[]   unmanagedNames  = new String[unmanaged.size()];
  221.         final double[][] unmanagedValues = new double[unmanaged.size()][];
  222.         int i = 0;
  223.         for (Map.Entry<String, double[]> entry : unmanaged.entrySet()) {
  224.             unmanagedNames[i]  = entry.getKey();
  225.             unmanagedValues[i] = entry.getValue();
  226.             ++i;
  227.         }

  228.         // managed states providers
  229.         final List<AdditionalStateProvider> serializableProviders = new ArrayList<AdditionalStateProvider>();
  230.         final List<String> equationNames = new ArrayList<String>();
  231.         for (final AdditionalStateProvider provider : getAdditionalStateProviders()) {
  232.             if (provider instanceof LocalProvider) {
  233.                 equationNames.add(((LocalProvider) provider).getName());
  234.             } else if (provider instanceof Serializable) {
  235.                 serializableProviders.add(provider);
  236.             }
  237.         }

  238.         return new DataTransferObject(startDate, minDate, maxDate, mapper, meanOrbit, model,
  239.                                       unmanagedNames, unmanagedValues,
  240.                                       serializableProviders.toArray(new AdditionalStateProvider[serializableProviders.size()]),
  241.                                       equationNames.toArray(new String[equationNames.size()]));

  242.     }

  243.     /** Local provider for additional state data. */
  244.     private class LocalProvider implements AdditionalStateProvider {

  245.         /** Name of the additional state. */
  246.         private final String name;

  247.         /** Index of the additional state. */
  248.         private final int index;

  249.         /** Simple constructor.
  250.          * @param name name of the additional state
  251.          * @param index index of the additional state
  252.          */
  253.         LocalProvider(final String name, final int index) {
  254.             this.name  = name;
  255.             this.index = index;
  256.         }

  257.         /** {@inheritDoc} */
  258.         public String getName() {
  259.             return name;
  260.         }

  261.         /** {@inheritDoc} */
  262.         public double[] getAdditionalState(final SpacecraftState state)
  263.             throws OrekitException {

  264.             // extract the part of the interpolated array corresponding to the additional state
  265.             return getInterpolatedState(state.getDate()).getSecondaryState(index + 1);

  266.         }

  267.     }

  268.     /** Internal class used only for serialization. */
  269.     private static class DataTransferObject implements Serializable {

  270.         /** Serializable UID. */
  271.         private static final long serialVersionUID = 20140213L;

  272.         /** Mapper between raw double components and spacecraft state. */
  273.         private final StateMapper mapper;

  274.         /** Indicator for mean orbit output. */
  275.         private final boolean meanOrbit;

  276.         /** Start date of the integration (can be min or max). */
  277.         private final AbsoluteDate startDate;

  278.         /** First date of the range. */
  279.         private final AbsoluteDate minDate;

  280.         /** Last date of the range. */
  281.         private final AbsoluteDate maxDate;

  282.         /** Underlying raw mathematical model. */
  283.         private final DenseOutputModel model;

  284.         /** Names of unmanaged additional states that must be simply copied. */
  285.         private final String[] unmanagedNames;

  286.         /** Values of unmanaged additional states that must be simply copied. */
  287.         private final double[][] unmanagedValues;

  288.         /** Names of additional equations. */
  289.         private final String[] equations;

  290.         /** Providers for pre-integrated states. */
  291.         private final AdditionalStateProvider[] providers;

  292.         /** Simple constructor.
  293.          * @param startDate Start date of the integration (can be minDate or maxDate)
  294.          * @param minDate first date of the range
  295.          * @param maxDate last date of the range
  296.          * @param mapper mapper between raw double components and spacecraft state
  297.          * @param meanOrbit output only the mean orbit.
  298.          * @param model underlying raw mathematical model
  299.          * @param unmanagedNames names of unmanaged additional states that must be simply copied
  300.          * @param unmanagedValues values of unmanaged additional states that must be simply copied
  301.          * @param providers providers for pre-integrated states
  302.          * @param equations names of additional equations
  303.          */
  304.         DataTransferObject(final AbsoluteDate startDate,
  305.                                   final AbsoluteDate minDate, final AbsoluteDate maxDate,
  306.                                   final StateMapper mapper, final boolean meanOrbit,
  307.                                   final DenseOutputModel model,
  308.                                   final String[] unmanagedNames, final double[][] unmanagedValues,
  309.                                   final AdditionalStateProvider[] providers,
  310.                                   final String[] equations) {
  311.             this.startDate       = startDate;
  312.             this.minDate         = minDate;
  313.             this.maxDate         = maxDate;
  314.             this.mapper          = mapper;
  315.             this.meanOrbit       = meanOrbit;
  316.             this.model           = model;
  317.             this.unmanagedNames  = unmanagedNames;
  318.             this.unmanagedValues = unmanagedValues;
  319.             this.providers       = providers;
  320.             this.equations       = equations;
  321.         }

  322.         /** Replace the deserialized data transfer object with a {@link IntegratedEphemeris}.
  323.          * @return replacement {@link IntegratedEphemeris}
  324.          */
  325.         private Object readResolve() {
  326.             try {
  327.                 final Map<String, double[]> unmanaged = new HashMap<String, double[]>(unmanagedNames.length);
  328.                 for (int i = 0; i < unmanagedNames.length; ++i) {
  329.                     unmanaged.put(unmanagedNames[i], unmanagedValues[i]);
  330.                 }
  331.                 return new IntegratedEphemeris(startDate, minDate, maxDate, mapper, meanOrbit, model,
  332.                                                unmanaged, Arrays.asList(providers), equations);
  333.             } catch (OrekitException oe) {
  334.                 throw new OrekitInternalError(oe);
  335.             }
  336.         }

  337.     }

  338. }