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