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