1 /* Copyright 2002-2025 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.conversion;
18
19 import org.orekit.attitudes.Attitude;
20 import org.orekit.attitudes.AttitudeProvider;
21 import org.orekit.attitudes.FrameAlignedProvider;
22 import org.orekit.estimation.leastsquares.DSSTBatchLSModel;
23 import org.orekit.estimation.leastsquares.ModelObserver;
24 import org.orekit.estimation.measurements.ObservedMeasurement;
25 import org.orekit.orbits.EquinoctialOrbit;
26 import org.orekit.orbits.Orbit;
27 import org.orekit.orbits.OrbitType;
28 import org.orekit.orbits.PositionAngleType;
29 import org.orekit.propagation.PropagationType;
30 import org.orekit.propagation.Propagator;
31 import org.orekit.propagation.SpacecraftState;
32 import org.orekit.propagation.integration.AdditionalDerivativesProvider;
33 import org.orekit.propagation.semianalytical.dsst.DSSTPropagator;
34 import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
35 import org.orekit.propagation.semianalytical.dsst.forces.DSSTNewtonianAttraction;
36 import org.orekit.utils.ParameterDriver;
37 import org.orekit.utils.ParameterDriversList;
38
39 import java.util.ArrayList;
40 import java.util.Collections;
41 import java.util.List;
42
43 /** Builder for DSST propagator.
44 * @author Bryan Cazabonne
45 * @since 10.0
46 */
47 public class DSSTPropagatorBuilder extends AbstractIntegratedPropagatorBuilder<DSSTPropagator> {
48
49 /** Force models used during the extrapolation of the orbit. */
50 private final List<DSSTForceModel> forceModels;
51
52 /** Type of the elements used to define the orbital state.*/
53 private PropagationType stateType;
54
55 /** Build a new instance.
56 * <p>
57 * The reference orbit is used as a model to {@link
58 * #createInitialOrbit() create initial orbit}. It defines the
59 * inertial frame, the central attraction coefficient, and is also used together
60 * with the {@code positionScale} to convert from the {@link
61 * ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
62 * callers of this builder to the real orbital parameters.
63 * The default attitude provider is aligned with the orbit's inertial frame.
64 * </p>
65 *
66 * @param referenceOrbit reference orbit from which real orbits will be built
67 * @param builder first order integrator builder
68 * @param positionScale scaling factor used for orbital parameters normalization
69 * (typically set to the expected standard deviation of the position)
70 * @param propagationType type of the orbit used for the propagation (mean or osculating)
71 * @param stateType type of the elements used to define the orbital state (mean or osculating)
72 * @see #DSSTPropagatorBuilder(Orbit, ODEIntegratorBuilder, double, PropagationType,
73 * PropagationType, AttitudeProvider)
74 */
75 public DSSTPropagatorBuilder(final Orbit referenceOrbit,
76 final ODEIntegratorBuilder builder,
77 final double positionScale,
78 final PropagationType propagationType,
79 final PropagationType stateType) {
80 this(referenceOrbit, builder, positionScale, propagationType, stateType,
81 FrameAlignedProvider.of(referenceOrbit.getFrame()));
82 }
83
84 /** Build a new instance.
85 * <p>
86 * The reference orbit is used as a model to {@link
87 * #createInitialOrbit() create initial orbit}. It defines the
88 * inertial frame, the central attraction coefficient, and is also used together
89 * with the {@code positionScale} to convert from the {@link
90 * ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
91 * callers of this builder to the real orbital parameters.
92 * </p>
93 * @param referenceOrbit reference orbit from which real orbits will be built
94 * @param builder first order integrator builder
95 * @param positionScale scaling factor used for orbital parameters normalization
96 * (typically set to the expected standard deviation of the position)
97 * @param propagationType type of the orbit used for the propagation (mean or osculating)
98 * @param stateType type of the elements used to define the orbital state (mean or osculating)
99 * @param attitudeProvider attitude law.
100 * @since 10.1
101 */
102 public DSSTPropagatorBuilder(final Orbit referenceOrbit,
103 final ODEIntegratorBuilder builder,
104 final double positionScale,
105 final PropagationType propagationType,
106 final PropagationType stateType,
107 final AttitudeProvider attitudeProvider) {
108 super(referenceOrbit, builder, PositionAngleType.MEAN, positionScale, propagationType, attitudeProvider, Propagator.DEFAULT_MASS);
109 this.forceModels = new ArrayList<>();
110 this.stateType = stateType;
111 }
112
113 /** Get the type of the elements used to define the orbital state (mean or osculating).
114 * @return the type of the elements used to define the orbital state
115 */
116 public PropagationType getStateType() {
117 return stateType;
118 }
119
120 /** Get the list of all force models.
121 * @return the list of all force models
122 */
123 public List<DSSTForceModel> getAllForceModels()
124 {
125 return Collections.unmodifiableList(forceModels);
126 }
127
128 /** Add a force model to the global perturbation model.
129 * <p>If this method is not called at all, the integrated orbit will follow
130 * a Keplerian evolution only.</p>
131 * @param model perturbing {@link DSSTForceModel} to add
132 */
133 public void addForceModel(final DSSTForceModel model) {
134 if (model instanceof DSSTNewtonianAttraction) {
135 // we want to add the central attraction force model
136 if (hasNewtonianAttraction()) {
137 // there is already a central attraction model, replace it
138 forceModels.set(forceModels.size() - 1, model);
139 } else {
140 // there are no central attraction model yet, add it at the end of the list
141 forceModels.add(model);
142 }
143 } else {
144 // we want to add a perturbing force model
145 if (hasNewtonianAttraction()) {
146 // insert the new force model before Newtonian attraction,
147 // which should always be the last one in the list
148 forceModels.add(forceModels.size() - 1, model);
149 } else {
150 // we only have perturbing force models up to now, just append at the end of the list
151 forceModels.add(model);
152 }
153 }
154
155 addSupportedParameters(model.getParametersDrivers());
156 }
157
158 /** Reset the orbit in the propagator builder.
159 * @param newOrbit newOrbit New orbit to set in the propagator builder
160 * @param orbitType orbit type (MEAN or OSCULATING)
161 */
162 public void resetOrbit(final Orbit newOrbit, final PropagationType orbitType) {
163 this.stateType = orbitType;
164 super.resetOrbit(newOrbit);
165 }
166
167 /** {@inheritDoc} */
168 public DSSTPropagator buildPropagator(final double[] normalizedParameters) {
169
170 setParameters(normalizedParameters);
171 final EquinoctialOrbit orbit = (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(createInitialOrbit());
172 final Attitude attitude = getAttitudeProvider().getAttitude(orbit, orbit.getDate(), getFrame());
173 final SpacecraftState state = new SpacecraftState(orbit, attitude).withMass(getMass());
174
175 final DSSTPropagator propagator = new DSSTPropagator(
176 getIntegratorBuilder().buildIntegrator(orbit, OrbitType.EQUINOCTIAL, PositionAngleType.MEAN),
177 getPropagationType(), getAttitudeProvider());
178
179 // Configure force models
180 if (!hasNewtonianAttraction()) {
181 // There are no central attraction model yet, add it at the end of the list
182 addForceModel(new DSSTNewtonianAttraction(orbit.getMu()));
183 }
184 for (DSSTForceModel model : forceModels) {
185 propagator.addForceModel(model);
186 }
187
188 propagator.setInitialState(state, stateType);
189
190 // Add additional derivatives providers to the propagator
191 for (AdditionalDerivativesProvider provider: getAdditionalDerivativesProviders()) {
192 propagator.addAdditionalDerivativesProvider(provider);
193 }
194
195 return propagator;
196
197 }
198
199 /** {@inheritDoc} */
200 @Override
201 public DSSTBatchLSModel buildLeastSquaresModel(final PropagatorBuilder[] builders,
202 final List<ObservedMeasurement<?>> measurements,
203 final ParameterDriversList estimatedMeasurementsParameters,
204 final ModelObserver observer) {
205 return new DSSTBatchLSModel(builders,
206 measurements,
207 estimatedMeasurementsParameters,
208 observer,
209 getPropagationType());
210 }
211
212 /** Check if Newtonian attraction force model is available.
213 * <p>
214 * Newtonian attraction is always the last force model in the list.
215 * </p>
216 * @return true if Newtonian attraction force model is available
217 */
218 private boolean hasNewtonianAttraction() {
219 final int last = forceModels.size() - 1;
220 return last >= 0 && forceModels.get(last) instanceof DSSTNewtonianAttraction;
221 }
222
223 }