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;
18  
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.List;
23  import java.util.Map;
24  
25  import org.orekit.attitudes.AttitudeProvider;
26  import org.orekit.errors.OrekitException;
27  import org.orekit.errors.OrekitMessages;
28  import org.orekit.frames.Frame;
29  import org.orekit.propagation.events.EventDetector;
30  import org.orekit.propagation.sampling.OrekitFixedStepHandler;
31  import org.orekit.propagation.sampling.OrekitStepHandler;
32  import org.orekit.propagation.sampling.OrekitStepNormalizer;
33  import org.orekit.time.AbsoluteDate;
34  import org.orekit.utils.TimeStampedPVCoordinates;
35  
36  /** Common handling of {@link Propagator} methods for analytical propagators.
37   * <p>
38   * This abstract class allows to provide easily the full set of {@link Propagator}
39   * methods, including all propagation modes support and discrete events support for
40   * any simple propagation method.
41   * </p>
42   * @author Luc Maisonobe
43   */
44  public abstract class AbstractPropagator implements Propagator {
45  
46      /** Propagation mode. */
47      private int mode;
48  
49      /** Fixed step size. */
50      private double fixedStepSize;
51  
52      /** Step handler. */
53      private OrekitStepHandler stepHandler;
54  
55      /** Start date. */
56      private AbsoluteDate startDate;
57  
58      /** Attitude provider. */
59      private AttitudeProvider attitudeProvider;
60  
61      /** Additional state providers. */
62      private final List<AdditionalStateProvider> additionalStateProviders;
63  
64      /** Initial state. */
65      private SpacecraftState initialState;
66  
67      /** Build a new instance.
68       */
69      protected AbstractPropagator() {
70          mode                     = SLAVE_MODE;
71          stepHandler              = null;
72          fixedStepSize            = Double.NaN;
73          additionalStateProviders = new ArrayList<AdditionalStateProvider>();
74      }
75  
76      /** Set a start date.
77       * @param startDate start date
78       */
79      protected void setStartDate(final AbsoluteDate startDate) {
80          this.startDate = startDate;
81      }
82  
83      /** Get the start date.
84       * @return start date
85       */
86      protected AbsoluteDate getStartDate() {
87          return startDate;
88      }
89  
90      /**  {@inheritDoc} */
91      public AttitudeProvider getAttitudeProvider() {
92          return attitudeProvider;
93      }
94  
95      /**  {@inheritDoc} */
96      public void setAttitudeProvider(final AttitudeProvider attitudeProvider) {
97          this.attitudeProvider = attitudeProvider;
98      }
99  
100     /** {@inheritDoc} */
101     public SpacecraftState getInitialState() throws OrekitException {
102         return initialState;
103     }
104 
105     /** {@inheritDoc} */
106     public int getMode() {
107         return mode;
108     }
109 
110     /** {@inheritDoc} */
111     public Frame getFrame() {
112         return initialState.getFrame();
113     }
114 
115     /** {@inheritDoc} */
116     public void resetInitialState(final SpacecraftState state) throws OrekitException {
117         initialState = state;
118         setStartDate(state.getDate());
119     }
120 
121     /** {@inheritDoc} */
122     public void setSlaveMode() {
123         mode          = SLAVE_MODE;
124         stepHandler   = null;
125         fixedStepSize = Double.NaN;
126     }
127 
128     /** {@inheritDoc} */
129     public void setMasterMode(final double h,
130                               final OrekitFixedStepHandler handler) {
131         setMasterMode(new OrekitStepNormalizer(h, handler));
132         fixedStepSize = h;
133     }
134 
135     /** {@inheritDoc} */
136     public void setMasterMode(final OrekitStepHandler handler) {
137         mode          = MASTER_MODE;
138         stepHandler   = handler;
139         fixedStepSize = Double.NaN;
140     }
141 
142     /** {@inheritDoc} */
143     public void setEphemerisMode() {
144         mode          = EPHEMERIS_GENERATION_MODE;
145         stepHandler   = null;
146         fixedStepSize = Double.NaN;
147     }
148 
149     /** {@inheritDoc} */
150     @Override
151     public void setEphemerisMode(final OrekitStepHandler handler) {
152         mode          = EPHEMERIS_GENERATION_MODE;
153         stepHandler   = handler;
154         fixedStepSize = Double.NaN;
155     }
156 
157     /** {@inheritDoc} */
158     public void addAdditionalStateProvider(final AdditionalStateProvider additionalStateProvider)
159         throws OrekitException {
160 
161         // check if the name is already used
162         if (isAdditionalStateManaged(additionalStateProvider.getName())) {
163             // this additional state is already registered, complain
164             throw new OrekitException(OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE,
165                                       additionalStateProvider.getName());
166         }
167 
168         // this is really a new name, add it
169         additionalStateProviders.add(additionalStateProvider);
170 
171     }
172 
173     /** {@inheritDoc} */
174     public List<AdditionalStateProvider> getAdditionalStateProviders() {
175         return Collections.unmodifiableList(additionalStateProviders);
176     }
177 
178     /** Update state by adding all additional states.
179      * @param original original state
180      * @return updated state, with all additional states included
181      * @exception OrekitException if one of the providers throws one
182      * @see #addAdditionalStateProvider(AdditionalStateProvider)
183      */
184     protected SpacecraftState updateAdditionalStates(final SpacecraftState original)
185         throws OrekitException {
186 
187         // start with original state,
188         // which may already contain additional states, for example in interpolated ephemerides
189         SpacecraftState updated = original;
190 
191         if (initialState != null) {
192             // there is an initial state
193             // (null initial states occur for example in interpolated ephemerides)
194             // copy the additional states present in initialState but otherwise not managed
195             for (final Map.Entry<String, double[]> initial : initialState.getAdditionalStates().entrySet()) {
196                 if (!isAdditionalStateManaged(initial.getKey())) {
197                     // this additional state was in the initial state, but is unknown to the propagator
198                     // we simply copy its initial value as is
199                     updated = updated.addAdditionalState(initial.getKey(), initial.getValue());
200                 }
201             }
202         }
203 
204         // update the additional states managed by providers
205         for (final AdditionalStateProvider provider : additionalStateProviders) {
206             updated = updated.addAdditionalState(provider.getName(),
207                                                  provider.getAdditionalState(updated));
208         }
209 
210         return updated;
211 
212     }
213 
214     /** {@inheritDoc} */
215     public boolean isAdditionalStateManaged(final String name) {
216         for (final AdditionalStateProvider provider : additionalStateProviders) {
217             if (provider.getName().equals(name)) {
218                 return true;
219             }
220         }
221         return false;
222     }
223 
224     /** {@inheritDoc} */
225     public String[] getManagedAdditionalStates() {
226         final String[] managed = new String[additionalStateProviders.size()];
227         for (int i = 0; i < managed.length; ++i) {
228             managed[i] = additionalStateProviders.get(i).getName();
229         }
230         return managed;
231     }
232 
233     /** Get the fixed step size.
234      * @return fixed step size (or NaN if there are no fixed step size).
235      */
236     protected double getFixedStepSize() {
237         return fixedStepSize;
238     }
239 
240     /** Get the step handler.
241      * @return step handler
242      */
243     protected OrekitStepHandler getStepHandler() {
244         return stepHandler;
245     }
246 
247     /** {@inheritDoc} */
248     public abstract BoundedPropagator getGeneratedEphemeris();
249 
250     /** {@inheritDoc} */
251     public abstract <T extends EventDetector> void addEventDetector(T detector);
252 
253     /** {@inheritDoc} */
254     public abstract Collection<EventDetector> getEventsDetectors();
255 
256     /** {@inheritDoc} */
257     public abstract void clearEventsDetectors();
258 
259     /** {@inheritDoc} */
260     public SpacecraftState propagate(final AbsoluteDate target) throws OrekitException {
261         if (startDate == null) {
262             startDate = getInitialState().getDate();
263         }
264         return propagate(startDate, target);
265     }
266 
267     /** {@inheritDoc} */
268     public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame)
269         throws OrekitException {
270         return propagate(date).getPVCoordinates(frame);
271     }
272 
273 }