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
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.hipparchus.CalculusFieldElement;
25 import org.hipparchus.util.MathArrays;
26 import org.orekit.attitudes.AttitudeProvider;
27 import org.orekit.attitudes.FieldAttitude;
28 import org.orekit.attitudes.InertialProvider;
29 import org.orekit.orbits.FieldOrbit;
30 import org.orekit.orbits.Orbit;
31 import org.orekit.orbits.OrbitType;
32 import org.orekit.orbits.PositionAngle;
33 import org.orekit.propagation.FieldSpacecraftState;
34 import org.orekit.time.FieldAbsoluteDate;
35 import org.orekit.utils.FieldTimeSpanMap;
36 import org.orekit.utils.ParameterDriver;
37
38 /** Simple Keplerian orbit propagator.
39 * @see FieldOrbit
40 * @author Guylaine Prat
41 */
42 public class FieldKeplerianPropagator<T extends CalculusFieldElement<T>> extends FieldAbstractAnalyticalPropagator<T> {
43
44
45 /** All states. */
46 private transient FieldTimeSpanMap<FieldSpacecraftState<T>, T> states;
47
48 /** Build a propagator from orbit only.
49 * <p>The central attraction coefficient μ is set to the same value used
50 * for the initial orbit definition. Mass and attitude provider are set to
51 * unspecified non-null arbitrary values.</p>
52 *
53 * @param initialFieldOrbit initial orbit
54 * @see #FieldKeplerianPropagator(FieldOrbit, AttitudeProvider)
55 */
56 public FieldKeplerianPropagator(final FieldOrbit<T> initialFieldOrbit) {
57 this(initialFieldOrbit, InertialProvider.of(initialFieldOrbit.getFrame()),
58 initialFieldOrbit.getMu(), initialFieldOrbit.getA().getField().getZero().add(DEFAULT_MASS));
59 }
60
61 /** Build a propagator from orbit and central attraction coefficient μ.
62 * <p>Mass and attitude provider are set to unspecified non-null arbitrary values.</p>
63 *
64 * @param initialFieldOrbit initial orbit
65 * @param mu central attraction coefficient (m³/s²)
66 * @see #FieldKeplerianPropagator(FieldOrbit, AttitudeProvider, CalculusFieldElement)
67 */
68 public FieldKeplerianPropagator(final FieldOrbit<T> initialFieldOrbit, final T mu) {
69 this(initialFieldOrbit, InertialProvider.of(initialFieldOrbit.getFrame()),
70 mu, initialFieldOrbit.getA().getField().getZero().add(DEFAULT_MASS));
71 }
72
73 /** Build a propagator from orbit and attitude provider.
74 * <p>The central attraction coefficient μ is set to the same value
75 * used for the initial orbit definition. Mass is set to an unspecified
76 * non-null arbitrary value.</p>
77 * @param initialFieldOrbit initial orbit
78 * @param attitudeProv attitude provider
79 */
80 public FieldKeplerianPropagator(final FieldOrbit<T> initialFieldOrbit,
81 final AttitudeProvider attitudeProv) {
82 this(initialFieldOrbit, attitudeProv, initialFieldOrbit.getMu(), initialFieldOrbit.getA().getField().getZero().add(DEFAULT_MASS));
83 }
84
85 /** Build a propagator from orbit, attitude provider and central attraction
86 * coefficient μ.
87 * <p>Mass is set to an unspecified non-null arbitrary value.</p>
88 * @param initialFieldOrbit initial orbit
89 * @param attitudeProv attitude provider
90 * @param mu central attraction coefficient (m³/s²)
91 */
92 public FieldKeplerianPropagator(final FieldOrbit<T> initialFieldOrbit,
93 final AttitudeProvider attitudeProv,
94 final T mu) {
95 this(initialFieldOrbit, attitudeProv, mu, initialFieldOrbit.getA().getField().getZero().add(DEFAULT_MASS));
96 }
97
98 /** Build propagator from orbit, attitude provider, central attraction
99 * coefficient μ and mass.
100 * @param initialOrbit initial orbit
101 * @param attitudeProv attitude provider
102 * @param mu central attraction coefficient (m³/s²)
103 * @param mass spacecraft mass (kg)
104 */
105 public FieldKeplerianPropagator(final FieldOrbit<T> initialOrbit, final AttitudeProvider attitudeProv,
106 final T mu, final T mass) {
107
108 super(initialOrbit.getA().getField(), attitudeProv);
109
110 // ensure the orbit use the specified mu and has no non-Keplerian derivatives
111 final FieldSpacecraftState<T> initial = fixState(initialOrbit,
112 getAttitudeProvider().getAttitude(initialOrbit,
113 initialOrbit.getDate(),
114 initialOrbit.getFrame()),
115 mass, mu, Collections.emptyMap());
116 states = new FieldTimeSpanMap<>(initial, initialOrbit.getA().getField());
117 super.resetInitialState(initial);
118 }
119
120 /** Fix state to use a specified mu and remove derivatives.
121 * <p>
122 * This ensures the propagation model (which is based on calling
123 * {@link Orbit#shiftedBy(double)}) is Keplerian only and uses a specified mu.
124 * </p>
125 * @param orbit orbit to fix
126 * @param attitude current attitude
127 * @param mass current mass
128 * @param mu gravity coefficient to use
129 * @param additionalStates additional states
130 * @return fixed orbit
131 */
132 private FieldSpacecraftState<T> fixState(final FieldOrbit<T> orbit, final FieldAttitude<T> attitude, final T mass,
133 final T mu, final Map<String, T[]> additionalStates) {
134 final OrbitType type = orbit.getType();
135 final T[] stateVector = MathArrays.buildArray(mass.getField(), 6);
136 type.mapOrbitToArray(orbit, PositionAngle.TRUE, stateVector, null);
137 final FieldOrbit<T> fixedOrbit = type.mapArrayToOrbit(stateVector, null, PositionAngle.TRUE,
138 orbit.getDate(), mu, orbit.getFrame());
139 FieldSpacecraftState<T> fixedState = new FieldSpacecraftState<>(fixedOrbit, attitude, mass);
140 for (final Map.Entry<String, T[]> entry : additionalStates.entrySet()) {
141 fixedState = fixedState.addAdditionalState(entry.getKey(), entry.getValue());
142 }
143 return fixedState;
144 }
145
146 /** {@inheritDoc} */
147 public void resetInitialState(final FieldSpacecraftState<T> state) {
148
149 // ensure the orbit use the specified mu and has no non-Keplerian derivatives
150 final FieldSpacecraftState<T> formerInitial = getInitialState();
151 final T mu = formerInitial == null ? state.getMu() : formerInitial.getMu();
152 final FieldSpacecraftState<T> fixedState = fixState(state.getOrbit(),
153 state.getAttitude(),
154 state.getMass(),
155 mu,
156 state.getAdditionalStates());
157
158 states = new FieldTimeSpanMap<>(fixedState, state.getDate().getField());
159 super.resetInitialState(fixedState);
160
161 }
162
163 /** {@inheritDoc} */
164 protected void resetIntermediateState(final FieldSpacecraftState<T> state, final boolean forward) {
165 if (forward) {
166 states.addValidAfter(state, state.getDate());
167 } else {
168 states.addValidBefore(state, state.getDate());
169 }
170 stateChanged(state);
171 }
172
173 /** {@inheritDoc} */
174 protected FieldOrbit<T> propagateOrbit(final FieldAbsoluteDate<T> date, final T[] parameters) {
175 // propagate orbit
176 FieldOrbit<T> orbit = states.get(date).getOrbit();
177 do {
178 // we use a loop here to compensate for very small date shifts error
179 // that occur with long propagation time
180 orbit = orbit.shiftedBy(date.durationFrom(orbit.getDate()));
181 } while (!date.equals(orbit.getDate()));
182 return orbit;
183 }
184
185 /** {@inheritDoc}*/
186 protected T getMass(final FieldAbsoluteDate<T> date) {
187 return states.get(date).getMass();
188 }
189
190 /** {@inheritDoc} */
191 @Override
192 protected List<ParameterDriver> getParametersDrivers() {
193 // Keplerian propagation model does not have parameter drivers.
194 return Collections.emptyList();
195 }
196
197 }