1 /* Copyright 2002-2024 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 AbstractPropagatorBuilder {
48
49 /** First order integrator builder for propagation. */
50 private final ODEIntegratorBuilder builder;
51
52 /** Force models used during the extrapolation of the orbit. */
53 private final List<DSSTForceModel> forceModels;
54
55 /** Current mass for initial state (kg). */
56 private double mass;
57
58 /** Type of the orbit used for the propagation.*/
59 private PropagationType propagationType;
60
61 /** Type of the elements used to define the orbital state.*/
62 private PropagationType stateType;
63
64 /** Build a new instance.
65 * <p>
66 * The reference orbit is used as a model to {@link
67 * #createInitialOrbit() create initial orbit}. It defines the
68 * inertial frame, the central attraction coefficient, and is also used together
69 * with the {@code positionScale} to convert from the {@link
70 * ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
71 * callers of this builder to the real orbital parameters.
72 * The default attitude provider is aligned with the orbit's inertial frame.
73 * </p>
74 *
75 * @param referenceOrbit reference orbit from which real orbits will be built
76 * @param builder first order integrator builder
77 * @param positionScale scaling factor used for orbital parameters normalization
78 * (typically set to the expected standard deviation of the position)
79 * @param propagationType type of the orbit used for the propagation (mean or osculating)
80 * @param stateType type of the elements used to define the orbital state (mean or osculating)
81 * @see #DSSTPropagatorBuilder(Orbit, ODEIntegratorBuilder, double, PropagationType,
82 * PropagationType, AttitudeProvider)
83 */
84 public DSSTPropagatorBuilder(final Orbit referenceOrbit,
85 final ODEIntegratorBuilder builder,
86 final double positionScale,
87 final PropagationType propagationType,
88 final PropagationType stateType) {
89 this(referenceOrbit, builder, positionScale, propagationType, stateType,
90 FrameAlignedProvider.of(referenceOrbit.getFrame()));
91 }
92
93 /** Build a new instance.
94 * <p>
95 * The reference orbit is used as a model to {@link
96 * #createInitialOrbit() create initial orbit}. It defines the
97 * inertial frame, the central attraction coefficient, and is also used together
98 * with the {@code positionScale} to convert from the {@link
99 * ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
100 * callers of this builder to the real orbital parameters.
101 * </p>
102 * @param referenceOrbit reference orbit from which real orbits will be built
103 * @param builder first order integrator builder
104 * @param positionScale scaling factor used for orbital parameters normalization
105 * (typically set to the expected standard deviation of the position)
106 * @param propagationType type of the orbit used for the propagation (mean or osculating)
107 * @param stateType type of the elements used to define the orbital state (mean or osculating)
108 * @param attitudeProvider attitude law.
109 * @since 10.1
110 */
111 public DSSTPropagatorBuilder(final Orbit referenceOrbit,
112 final ODEIntegratorBuilder builder,
113 final double positionScale,
114 final PropagationType propagationType,
115 final PropagationType stateType,
116 final AttitudeProvider attitudeProvider) {
117 super(referenceOrbit, PositionAngleType.MEAN, positionScale, true, attitudeProvider);
118 this.builder = builder;
119 this.forceModels = new ArrayList<>();
120 this.mass = Propagator.DEFAULT_MASS;
121 this.propagationType = propagationType;
122 this.stateType = stateType;
123 }
124
125 /** Get the type of the orbit used for the propagation (mean or osculating).
126 * @return the type of the orbit used for the propagation
127 */
128 public PropagationType getPropagationType() {
129 return propagationType;
130 }
131
132 /** Get the type of the elements used to define the orbital state (mean or osculating).
133 * @return the type of the elements used to define the orbital state
134 */
135 public PropagationType getStateType() {
136 return stateType;
137 }
138
139 /** Create a copy of a DSSTPropagatorBuilder object.
140 * @return Copied version of the DSSTPropagatorBuilder
141 */
142 public DSSTPropagatorBuilder copy() {
143 final DSSTPropagatorBuilder copyBuilder =
144 new DSSTPropagatorBuilder(createInitialOrbit(),
145 builder,
146 getPositionScale(),
147 propagationType,
148 stateType,
149 getAttitudeProvider());
150 copyBuilder.setMass(mass);
151 for (DSSTForceModel model : forceModels) {
152 copyBuilder.addForceModel(model);
153 }
154 return copyBuilder;
155 }
156
157 /** Get the integrator builder.
158 * @return the integrator builder
159 */
160 public ODEIntegratorBuilder getIntegratorBuilder()
161 {
162 return builder;
163 }
164
165 /** Get the list of all force models.
166 * @return the list of all force models
167 */
168 public List<DSSTForceModel> getAllForceModels()
169 {
170 return Collections.unmodifiableList(forceModels);
171 }
172
173 /** Get the mass.
174 * @return the mass
175 */
176 public double getMass()
177 {
178 return mass;
179 }
180
181 /** Set the initial mass.
182 * @param mass the mass (kg)
183 */
184 public void setMass(final double mass) {
185 this.mass = mass;
186 }
187
188 /** Add a force model to the global perturbation model.
189 * <p>If this method is not called at all, the integrated orbit will follow
190 * a Keplerian evolution only.</p>
191 * @param model perturbing {@link DSSTForceModel} to add
192 */
193 public void addForceModel(final DSSTForceModel model) {
194 if (model instanceof DSSTNewtonianAttraction) {
195 // we want to add the central attraction force model
196 if (hasNewtonianAttraction()) {
197 // there is already a central attraction model, replace it
198 forceModels.set(forceModels.size() - 1, model);
199 } else {
200 // there are no central attraction model yet, add it at the end of the list
201 forceModels.add(model);
202 }
203 } else {
204 // we want to add a perturbing force model
205 if (hasNewtonianAttraction()) {
206 // insert the new force model before Newtonian attraction,
207 // which should always be the last one in the list
208 forceModels.add(forceModels.size() - 1, model);
209 } else {
210 // we only have perturbing force models up to now, just append at the end of the list
211 forceModels.add(model);
212 }
213 }
214
215 addSupportedParameters(model.getParametersDrivers());
216 }
217
218 /** Reset the orbit in the propagator builder.
219 * @param newOrbit newOrbit New orbit to set in the propagator builder
220 * @param orbitType orbit type (MEAN or OSCULATING)
221 */
222 public void resetOrbit(final Orbit newOrbit, final PropagationType orbitType) {
223 this.stateType = orbitType;
224 super.resetOrbit(newOrbit);
225 }
226
227 /** {@inheritDoc} */
228 public DSSTPropagator buildPropagator(final double[] normalizedParameters) {
229
230 setParameters(normalizedParameters);
231 final EquinoctialOrbit orbit = (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(createInitialOrbit());
232 final Attitude attitude = getAttitudeProvider().getAttitude(orbit, orbit.getDate(), getFrame());
233 final SpacecraftState state = new SpacecraftState(orbit, attitude, mass);
234
235 final DSSTPropagator propagator = new DSSTPropagator(
236 builder.buildIntegrator(orbit, OrbitType.EQUINOCTIAL),
237 propagationType,
238 getAttitudeProvider());
239
240 // Configure force models
241 if (!hasNewtonianAttraction()) {
242 // There are no central attraction model yet, add it at the end of the list
243 addForceModel(new DSSTNewtonianAttraction(orbit.getMu()));
244 }
245 for (DSSTForceModel model : forceModels) {
246 propagator.addForceModel(model);
247 }
248
249 propagator.setInitialState(state, stateType);
250
251 // Add additional derivatives providers to the propagator
252 for (AdditionalDerivativesProvider provider: getAdditionalDerivativesProviders()) {
253 propagator.addAdditionalDerivativesProvider(provider);
254 }
255
256 return propagator;
257
258 }
259
260 /** {@inheritDoc} */
261 @Override
262 public DSSTBatchLSModel buildLeastSquaresModel(final PropagatorBuilder[] builders,
263 final List<ObservedMeasurement<?>> measurements,
264 final ParameterDriversList estimatedMeasurementsParameters,
265 final ModelObserver observer) {
266 return new DSSTBatchLSModel(builders,
267 measurements,
268 estimatedMeasurementsParameters,
269 observer,
270 propagationType);
271 }
272
273 /** Check if Newtonian attraction force model is available.
274 * <p>
275 * Newtonian attraction is always the last force model in the list.
276 * </p>
277 * @return true if Newtonian attraction force model is available
278 */
279 private boolean hasNewtonianAttraction() {
280 final int last = forceModels.size() - 1;
281 return last >= 0 && forceModels.get(last) instanceof DSSTNewtonianAttraction;
282 }
283
284 }