1   /* Copyright 2002-2019 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() {
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) {
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 
160         // check if the name is already used
161         if (isAdditionalStateManaged(additionalStateProvider.getName())) {
162             // this additional state is already registered, complain
163             throw new OrekitException(OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE,
164                                       additionalStateProvider.getName());
165         }
166 
167         // this is really a new name, add it
168         additionalStateProviders.add(additionalStateProvider);
169 
170     }
171 
172     /** {@inheritDoc} */
173     public List<AdditionalStateProvider> getAdditionalStateProviders() {
174         return Collections.unmodifiableList(additionalStateProviders);
175     }
176 
177     /** Update state by adding all additional states.
178      * @param original original state
179      * @return updated state, with all additional states included
180           * @see #addAdditionalStateProvider(AdditionalStateProvider)
181      */
182     protected SpacecraftStateate">SpacecraftState updateAdditionalStates(final SpacecraftState original) {
183 
184         // start with original state,
185         // which may already contain additional states, for example in interpolated ephemerides
186         SpacecraftState updated = original;
187 
188         if (initialState != null) {
189             // there is an initial state
190             // (null initial states occur for example in interpolated ephemerides)
191             // copy the additional states present in initialState but otherwise not managed
192             for (final Map.Entry<String, double[]> initial : initialState.getAdditionalStates().entrySet()) {
193                 if (!isAdditionalStateManaged(initial.getKey())) {
194                     // this additional state was in the initial state, but is unknown to the propagator
195                     // we simply copy its initial value as is
196                     updated = updated.addAdditionalState(initial.getKey(), initial.getValue());
197                 }
198             }
199         }
200 
201         // update the additional states managed by providers
202         for (final AdditionalStateProvider provider : additionalStateProviders) {
203             updated = updated.addAdditionalState(provider.getName(),
204                                                  provider.getAdditionalState(updated));
205         }
206 
207         return updated;
208 
209     }
210 
211     /** {@inheritDoc} */
212     public boolean isAdditionalStateManaged(final String name) {
213         for (final AdditionalStateProvider provider : additionalStateProviders) {
214             if (provider.getName().equals(name)) {
215                 return true;
216             }
217         }
218         return false;
219     }
220 
221     /** {@inheritDoc} */
222     public String[] getManagedAdditionalStates() {
223         final String[] managed = new String[additionalStateProviders.size()];
224         for (int i = 0; i < managed.length; ++i) {
225             managed[i] = additionalStateProviders.get(i).getName();
226         }
227         return managed;
228     }
229 
230     /** Get the fixed step size.
231      * @return fixed step size (or NaN if there are no fixed step size).
232      */
233     protected double getFixedStepSize() {
234         return fixedStepSize;
235     }
236 
237     /** Get the step handler.
238      * @return step handler
239      */
240     protected OrekitStepHandler getStepHandler() {
241         return stepHandler;
242     }
243 
244     /** {@inheritDoc} */
245     public abstract BoundedPropagator getGeneratedEphemeris();
246 
247     /** {@inheritDoc} */
248     public abstract <T extends EventDetector> void addEventDetector(T detector);
249 
250     /** {@inheritDoc} */
251     public abstract Collection<EventDetector> getEventsDetectors();
252 
253     /** {@inheritDoc} */
254     public abstract void clearEventsDetectors();
255 
256     /** {@inheritDoc} */
257     public SpacecraftState propagate(final AbsoluteDate target) {
258         if (startDate == null) {
259             startDate = getInitialState().getDate();
260         }
261         return propagate(startDate, target);
262     }
263 
264     /** {@inheritDoc} */
265     public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
266         return propagate(date).getPVCoordinates(frame);
267     }
268 
269 }