AbstractPropagator.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.propagation;

  18. import java.util.ArrayList;
  19. import java.util.Collection;
  20. import java.util.Collections;
  21. import java.util.HashMap;
  22. import java.util.List;
  23. import java.util.Map;

  24. import org.orekit.attitudes.AttitudeProvider;
  25. import org.orekit.errors.OrekitException;
  26. import org.orekit.errors.OrekitMessages;
  27. import org.orekit.frames.Frame;
  28. import org.orekit.propagation.events.EventDetector;
  29. import org.orekit.propagation.sampling.OrekitFixedStepHandler;
  30. import org.orekit.propagation.sampling.OrekitStepHandler;
  31. import org.orekit.propagation.sampling.OrekitStepNormalizer;
  32. import org.orekit.time.AbsoluteDate;
  33. import org.orekit.utils.TimeSpanMap;
  34. import org.orekit.utils.TimeStampedPVCoordinates;

  35. /** Common handling of {@link Propagator} methods for analytical propagators.
  36.  * <p>
  37.  * This abstract class allows to provide easily the full set of {@link Propagator}
  38.  * methods, including all propagation modes support and discrete events support for
  39.  * any simple propagation method.
  40.  * </p>
  41.  * @author Luc Maisonobe
  42.  */
  43. public abstract class AbstractPropagator implements Propagator {

  44.     /** Propagation mode. */
  45.     private int mode;

  46.     /** Fixed step size. */
  47.     private double fixedStepSize;

  48.     /** Step handler. */
  49.     private OrekitStepHandler stepHandler;

  50.     /** Start date. */
  51.     private AbsoluteDate startDate;

  52.     /** Attitude provider. */
  53.     private AttitudeProvider attitudeProvider;

  54.     /** Additional state providers. */
  55.     private final List<AdditionalStateProvider> additionalStateProviders;

  56.     /** States managed by neither additional equations nor state providers. */
  57.     private final Map<String, TimeSpanMap<double[]>> unmanagedStates;

  58.     /** Initial state. */
  59.     private SpacecraftState initialState;

  60.     /** Build a new instance.
  61.      */
  62.     protected AbstractPropagator() {
  63.         mode                     = SLAVE_MODE;
  64.         stepHandler              = null;
  65.         fixedStepSize            = Double.NaN;
  66.         additionalStateProviders = new ArrayList<AdditionalStateProvider>();
  67.         unmanagedStates          = new HashMap<>();
  68.     }

  69.     /** Set a start date.
  70.      * @param startDate start date
  71.      */
  72.     protected void setStartDate(final AbsoluteDate startDate) {
  73.         this.startDate = startDate;
  74.     }

  75.     /** Get the start date.
  76.      * @return start date
  77.      */
  78.     protected AbsoluteDate getStartDate() {
  79.         return startDate;
  80.     }

  81.     /**  {@inheritDoc} */
  82.     public AttitudeProvider getAttitudeProvider() {
  83.         return attitudeProvider;
  84.     }

  85.     /**  {@inheritDoc} */
  86.     public void setAttitudeProvider(final AttitudeProvider attitudeProvider) {
  87.         this.attitudeProvider = attitudeProvider;
  88.     }

  89.     /** {@inheritDoc} */
  90.     public SpacecraftState getInitialState() {
  91.         return initialState;
  92.     }

  93.     /** {@inheritDoc} */
  94.     public int getMode() {
  95.         return mode;
  96.     }

  97.     /** {@inheritDoc} */
  98.     public Frame getFrame() {
  99.         return initialState.getFrame();
  100.     }

  101.     /** {@inheritDoc} */
  102.     public void resetInitialState(final SpacecraftState state) {
  103.         initialState = state;
  104.         setStartDate(state.getDate());
  105.     }

  106.     /** {@inheritDoc} */
  107.     public void setSlaveMode() {
  108.         mode          = SLAVE_MODE;
  109.         stepHandler   = null;
  110.         fixedStepSize = Double.NaN;
  111.     }

  112.     /** {@inheritDoc} */
  113.     public void setMasterMode(final double h,
  114.                               final OrekitFixedStepHandler handler) {
  115.         setMasterMode(new OrekitStepNormalizer(h, handler));
  116.         fixedStepSize = h;
  117.     }

  118.     /** {@inheritDoc} */
  119.     public void setMasterMode(final OrekitStepHandler handler) {
  120.         mode          = MASTER_MODE;
  121.         stepHandler   = handler;
  122.         fixedStepSize = Double.NaN;
  123.     }

  124.     /** {@inheritDoc} */
  125.     public void setEphemerisMode() {
  126.         mode          = EPHEMERIS_GENERATION_MODE;
  127.         stepHandler   = null;
  128.         fixedStepSize = Double.NaN;
  129.     }

  130.     /** {@inheritDoc} */
  131.     @Override
  132.     public void setEphemerisMode(final OrekitStepHandler handler) {
  133.         mode          = EPHEMERIS_GENERATION_MODE;
  134.         stepHandler   = handler;
  135.         fixedStepSize = Double.NaN;
  136.     }

  137.     /** {@inheritDoc} */
  138.     public void addAdditionalStateProvider(final AdditionalStateProvider additionalStateProvider) {

  139.         // check if the name is already used
  140.         if (isAdditionalStateManaged(additionalStateProvider.getName())) {
  141.             // this additional state is already registered, complain
  142.             throw new OrekitException(OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE,
  143.                                       additionalStateProvider.getName());
  144.         }

  145.         // this is really a new name, add it
  146.         additionalStateProviders.add(additionalStateProvider);

  147.     }

  148.     /** {@inheritDoc} */
  149.     public List<AdditionalStateProvider> getAdditionalStateProviders() {
  150.         return Collections.unmodifiableList(additionalStateProviders);
  151.     }

  152.     /** Update state by adding all additional states.
  153.      * @param original original state
  154.      * @return updated state, with all additional states included
  155.      * @see #addAdditionalStateProvider(AdditionalStateProvider)
  156.      */
  157.     protected SpacecraftState updateAdditionalStates(final SpacecraftState original) {

  158.         // start with original state,
  159.         // which may already contain additional states, for example in interpolated ephemerides
  160.         SpacecraftState updated = original;

  161.         // update the states not managed by providers
  162.         for (final Map.Entry<String, TimeSpanMap<double[]>> entry : unmanagedStates.entrySet()) {
  163.             updated = updated.addAdditionalState(entry.getKey(),
  164.                                                  entry.getValue().get(original.getDate()));
  165.         }

  166.         // update the additional states managed by providers
  167.         for (final AdditionalStateProvider provider : additionalStateProviders) {
  168.             updated = updated.addAdditionalState(provider.getName(),
  169.                                                  provider.getAdditionalState(updated));
  170.         }

  171.         return updated;

  172.     }

  173.     /** {@inheritDoc} */
  174.     public boolean isAdditionalStateManaged(final String name) {
  175.         for (final AdditionalStateProvider provider : additionalStateProviders) {
  176.             if (provider.getName().equals(name)) {
  177.                 return true;
  178.             }
  179.         }
  180.         return false;
  181.     }

  182.     /** {@inheritDoc} */
  183.     public String[] getManagedAdditionalStates() {
  184.         final String[] managed = new String[additionalStateProviders.size()];
  185.         for (int i = 0; i < managed.length; ++i) {
  186.             managed[i] = additionalStateProviders.get(i).getName();
  187.         }
  188.         return managed;
  189.     }

  190.     /** Get the fixed step size.
  191.      * @return fixed step size (or NaN if there are no fixed step size).
  192.      */
  193.     protected double getFixedStepSize() {
  194.         return fixedStepSize;
  195.     }

  196.     /** Get the step handler.
  197.      * @return step handler
  198.      */
  199.     protected OrekitStepHandler getStepHandler() {
  200.         return stepHandler;
  201.     }

  202.     /** {@inheritDoc} */
  203.     public abstract BoundedPropagator getGeneratedEphemeris();

  204.     /** {@inheritDoc} */
  205.     public abstract <T extends EventDetector> void addEventDetector(T detector);

  206.     /** {@inheritDoc} */
  207.     public abstract Collection<EventDetector> getEventsDetectors();

  208.     /** {@inheritDoc} */
  209.     public abstract void clearEventsDetectors();

  210.     /** {@inheritDoc} */
  211.     public SpacecraftState propagate(final AbsoluteDate target) {
  212.         if (startDate == null) {
  213.             startDate = getInitialState().getDate();
  214.         }
  215.         return propagate(startDate, target);
  216.     }

  217.     /** {@inheritDoc} */
  218.     public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
  219.         return propagate(date).getPVCoordinates(frame);
  220.     }

  221.     /** Initialize propagation.
  222.      * @since 10.1
  223.      */
  224.     protected void initializePropagation() {

  225.         unmanagedStates.clear();

  226.         if (initialState != null) {
  227.             // there is an initial state
  228.             // (null initial states occur for example in interpolated ephemerides)
  229.             // copy the additional states present in initialState but otherwise not managed
  230.             for (final Map.Entry<String, double[]> initial : initialState.getAdditionalStates().entrySet()) {
  231.                 if (!isAdditionalStateManaged(initial.getKey())) {
  232.                     // this additional state is in the initial state, but is unknown to the propagator
  233.                     // we store it in a way event handlers may change it
  234.                     unmanagedStates.put(initial.getKey(), new TimeSpanMap<>(initial.getValue()));
  235.                 }
  236.             }
  237.         }
  238.     }

  239.     /** Notify about a state change.
  240.      * @param state new state
  241.      */
  242.     protected void stateChanged(final SpacecraftState state) {
  243.         final AbsoluteDate date    = state.getDate();
  244.         final boolean      forward = date.durationFrom(getStartDate()) >= 0.0;
  245.         for (final Map.Entry<String, double[]> changed : state.getAdditionalStates().entrySet()) {
  246.             final TimeSpanMap<double[]> tsm = unmanagedStates.get(changed.getKey());
  247.             if (tsm != null) {
  248.                 // this is an unmanaged state
  249.                 if (forward) {
  250.                     tsm.addValidAfter(changed.getValue(), date);
  251.                 } else {
  252.                     tsm.addValidBefore(changed.getValue(), date);
  253.                 }
  254.             }
  255.         }
  256.     }

  257. }