AbstractPropagator.java

  1. /* Copyright 2002-2021 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.Collections;
  20. import java.util.HashMap;
  21. import java.util.List;
  22. import java.util.Map;

  23. import org.orekit.attitudes.AttitudeProvider;
  24. import org.orekit.errors.OrekitException;
  25. import org.orekit.errors.OrekitMessages;
  26. import org.orekit.frames.Frame;
  27. import org.orekit.propagation.sampling.StepHandlerMultiplexer;
  28. import org.orekit.time.AbsoluteDate;
  29. import org.orekit.utils.TimeSpanMap;
  30. import org.orekit.utils.TimeStampedPVCoordinates;

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

  40.     /** Multiplexer for step handlers. */
  41.     private StepHandlerMultiplexer multiplexer;

  42.     /** Start date. */
  43.     private AbsoluteDate startDate;

  44.     /** Attitude provider. */
  45.     private AttitudeProvider attitudeProvider;

  46.     /** Additional state providers. */
  47.     private final List<AdditionalStateProvider> additionalStateProviders;

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

  50.     /** Initial state. */
  51.     private SpacecraftState initialState;

  52.     /** Build a new instance.
  53.      */
  54.     protected AbstractPropagator() {
  55.         multiplexer              = new StepHandlerMultiplexer();
  56.         additionalStateProviders = new ArrayList<AdditionalStateProvider>();
  57.         unmanagedStates          = new HashMap<>();
  58.     }

  59.     /** Set a start date.
  60.      * @param startDate start date
  61.      */
  62.     protected void setStartDate(final AbsoluteDate startDate) {
  63.         this.startDate = startDate;
  64.     }

  65.     /** Get the start date.
  66.      * @return start date
  67.      */
  68.     protected AbsoluteDate getStartDate() {
  69.         return startDate;
  70.     }

  71.     /**  {@inheritDoc} */
  72.     public AttitudeProvider getAttitudeProvider() {
  73.         return attitudeProvider;
  74.     }

  75.     /**  {@inheritDoc} */
  76.     public void setAttitudeProvider(final AttitudeProvider attitudeProvider) {
  77.         this.attitudeProvider = attitudeProvider;
  78.     }

  79.     /** {@inheritDoc} */
  80.     public SpacecraftState getInitialState() {
  81.         return initialState;
  82.     }

  83.     /** {@inheritDoc} */
  84.     public Frame getFrame() {
  85.         return initialState.getFrame();
  86.     }

  87.     /** {@inheritDoc} */
  88.     public void resetInitialState(final SpacecraftState state) {
  89.         initialState = state;
  90.         setStartDate(state.getDate());
  91.     }

  92.     /** {@inheritDoc} */
  93.     public StepHandlerMultiplexer getMultiplexer() {
  94.         return multiplexer;
  95.     }

  96.     /** {@inheritDoc} */
  97.     public void addAdditionalStateProvider(final AdditionalStateProvider additionalStateProvider) {

  98.         // check if the name is already used
  99.         if (isAdditionalStateManaged(additionalStateProvider.getName())) {
  100.             // this additional state is already registered, complain
  101.             throw new OrekitException(OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE,
  102.                                       additionalStateProvider.getName());
  103.         }

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

  106.     }

  107.     /** {@inheritDoc} */
  108.     public List<AdditionalStateProvider> getAdditionalStateProviders() {
  109.         return Collections.unmodifiableList(additionalStateProviders);
  110.     }

  111.     /** Update state by adding all additional states.
  112.      * @param original original state
  113.      * @return updated state, with all additional states included
  114.      * @see #addAdditionalStateProvider(AdditionalStateProvider)
  115.      */
  116.     protected SpacecraftState updateAdditionalStates(final SpacecraftState original) {

  117.         // start with original state,
  118.         // which may already contain additional states, for example in interpolated ephemerides
  119.         SpacecraftState updated = original;

  120.         // update the states not managed by providers
  121.         for (final Map.Entry<String, TimeSpanMap<double[]>> entry : unmanagedStates.entrySet()) {
  122.             updated = updated.addAdditionalState(entry.getKey(),
  123.                                                  entry.getValue().get(original.getDate()));
  124.         }

  125.         // update the additional states managed by providers
  126.         for (final AdditionalStateProvider provider : additionalStateProviders) {
  127.             updated = updated.addAdditionalState(provider.getName(),
  128.                                                  provider.getAdditionalState(updated));
  129.         }

  130.         return updated;

  131.     }

  132.     /** {@inheritDoc} */
  133.     public boolean isAdditionalStateManaged(final String name) {
  134.         for (final AdditionalStateProvider provider : additionalStateProviders) {
  135.             if (provider.getName().equals(name)) {
  136.                 return true;
  137.             }
  138.         }
  139.         return false;
  140.     }

  141.     /** {@inheritDoc} */
  142.     public String[] getManagedAdditionalStates() {
  143.         final String[] managed = new String[additionalStateProviders.size()];
  144.         for (int i = 0; i < managed.length; ++i) {
  145.             managed[i] = additionalStateProviders.get(i).getName();
  146.         }
  147.         return managed;
  148.     }

  149.     /** {@inheritDoc} */
  150.     public SpacecraftState propagate(final AbsoluteDate target) {
  151.         if (startDate == null) {
  152.             startDate = getInitialState().getDate();
  153.         }
  154.         return propagate(startDate, target);
  155.     }

  156.     /** {@inheritDoc} */
  157.     public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
  158.         return propagate(date).getPVCoordinates(frame);
  159.     }

  160.     /** Initialize propagation.
  161.      * @since 10.1
  162.      */
  163.     protected void initializePropagation() {

  164.         unmanagedStates.clear();

  165.         if (initialState != null) {
  166.             // there is an initial state
  167.             // (null initial states occur for example in interpolated ephemerides)
  168.             // copy the additional states present in initialState but otherwise not managed
  169.             for (final Map.Entry<String, double[]> initial : initialState.getAdditionalStates().entrySet()) {
  170.                 if (!isAdditionalStateManaged(initial.getKey())) {
  171.                     // this additional state is in the initial state, but is unknown to the propagator
  172.                     // we store it in a way event handlers may change it
  173.                     unmanagedStates.put(initial.getKey(), new TimeSpanMap<>(initial.getValue()));
  174.                 }
  175.             }
  176.         }
  177.     }

  178.     /** Notify about a state change.
  179.      * @param state new state
  180.      */
  181.     protected void stateChanged(final SpacecraftState state) {
  182.         final AbsoluteDate date    = state.getDate();
  183.         final boolean      forward = date.durationFrom(getStartDate()) >= 0.0;
  184.         for (final Map.Entry<String, double[]> changed : state.getAdditionalStates().entrySet()) {
  185.             final TimeSpanMap<double[]> tsm = unmanagedStates.get(changed.getKey());
  186.             if (tsm != null) {
  187.                 // this is an unmanaged state
  188.                 if (forward) {
  189.                     tsm.addValidAfter(changed.getValue(), date);
  190.                 } else {
  191.                     tsm.addValidBefore(changed.getValue(), date);
  192.                 }
  193.             }
  194.         }
  195.     }

  196. }