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.analytical;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.orekit.errors.OrekitException;
25 import org.orekit.errors.OrekitMessages;
26 import org.orekit.orbits.Orbit;
27 import org.orekit.propagation.Propagator;
28 import org.orekit.propagation.SpacecraftState;
29 import org.orekit.time.AbsoluteDate;
30
31 /** Orbit propagator that adapts an underlying propagator, adding {@link
32 * DifferentialEffect differential effects}.
33 * <p>
34 * This propagator is used when a reference propagator does not handle
35 * some effects that we need. A typical example would be an ephemeris
36 * that was computed for a reference orbit, and we want to compute a
37 * station-keeping maneuver on top of this ephemeris, changing its
38 * final state. The principal is to add one or more {@link
39 * org.orekit.forces.maneuvers.SmallManeuverAnalyticalModel small maneuvers
40 * analytical models} to it and use it as a new propagator, which takes the
41 * maneuvers into account.
42 * </p>
43 * <p>
44 * From a space flight dynamics point of view, this is a differential
45 * correction approach. From a computer science point of view, this is
46 * a use of the decorator design pattern.
47 * </p>
48 * @see Propagator
49 * @see org.orekit.forces.maneuvers.SmallManeuverAnalyticalModel
50 * @author Luc Maisonobe
51 */
52 public class AdapterPropagator extends AbstractAnalyticalPropagator {
53
54 /** Interface for orbit differential effects. */
55 public interface DifferentialEffect {
56
57 /** Apply the effect to a {@link SpacecraftState spacecraft state}.
58 * <p>
59 * Applying the effect may be a no-op in some cases. A typical example
60 * is maneuvers, for which the state is changed only for time <em>after</em>
61 * the maneuver occurrence.
62 * </p>
63 * @param original original state <em>without</em> the effect
64 * @return updated state at the same date, taking the effect
65 * into account if meaningful
66 */
67 SpacecraftState apply(SpacecraftState original);
68
69 }
70
71 /** Underlying reference propagator. */
72 private Propagator reference;
73
74 /** Effects to add. */
75 private List<DifferentialEffect> effects;
76
77 /** Build a propagator from an underlying reference propagator.
78 * <p>The reference propagator can be almost anything, numerical,
79 * analytical, and even an ephemeris. It may already take some maneuvers
80 * into account.</p>
81 * @param reference reference propagator
82 */
83 public AdapterPropagator(final Propagator reference) {
84 super(reference.getAttitudeProvider());
85 this.reference = reference;
86 this.effects = new ArrayList<DifferentialEffect>();
87 }
88
89 /** Add a differential effect.
90 * @param effect differential effect
91 */
92 public void addEffect(final DifferentialEffect effect) {
93 effects.add(effect);
94 }
95
96 /** Get the reference propagator.
97 * @return reference propagator
98 */
99 public Propagator getPropagator() {
100 return reference;
101 }
102
103 /** Get the differential effects.
104 * @return differential effects models, as an unmodifiable list
105 */
106 public List<DifferentialEffect> getEffects() {
107 return Collections.unmodifiableList(effects);
108 }
109
110 /** {@inheritDoc} */
111 public SpacecraftState getInitialState() {
112 return reference.getInitialState();
113 }
114
115 /** {@inheritDoc} */
116 @Override
117 public void resetInitialState(final SpacecraftState state) {
118 reference.resetInitialState(state);
119 }
120
121 /** {@inheritDoc} */
122 protected void resetIntermediateState(final SpacecraftState state, final boolean forward) {
123 if (reference instanceof AbstractAnalyticalPropagator) {
124 ((AbstractAnalyticalPropagator) reference).resetIntermediateState(state, forward);
125 } else {
126 throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
127 }
128 }
129
130 /** {@inheritDoc} */
131 @Override
132 protected SpacecraftState basicPropagate(final AbsoluteDate date) {
133
134 // compute reference state
135 SpacecraftState state = reference.propagate(date);
136 final Map<String, double[]> before = state.getAdditionalStates();
137
138 // add all the effects
139 for (final DifferentialEffect effect : effects) {
140 state = effect.apply(state);
141 }
142
143 // forward additional states from the reference propagator
144 for (final Map.Entry<String, double[]> entry : before.entrySet()) {
145 if (!state.hasAdditionalState(entry.getKey())) {
146 state = state.addAdditionalState(entry.getKey(), entry.getValue());
147 }
148 }
149
150 return state;
151
152 }
153
154 /** {@inheritDoc} */
155 protected Orbit propagateOrbit(final AbsoluteDate date) {
156 return basicPropagate(date).getOrbit();
157 }
158
159 /** {@inheritDoc}*/
160 protected double getMass(final AbsoluteDate date) {
161 return basicPropagate(date).getMass();
162 }
163
164 }