1   /* Copyright 2022-2026 Bryan Cazabonne
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    * Bryan Cazabonne 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.AttitudeProvider;
20  import org.orekit.attitudes.FrameAlignedProvider;
21  import org.orekit.estimation.leastsquares.AbstractBatchLSModel;
22  import org.orekit.estimation.leastsquares.BatchLSModel;
23  import org.orekit.estimation.leastsquares.ModelObserver;
24  import org.orekit.estimation.measurements.ObservedMeasurement;
25  import org.orekit.orbits.AbstractOrbitFactory;
26  import org.orekit.orbits.Orbit;
27  import org.orekit.orbits.PositionAngleType;
28  import org.orekit.propagation.SpacecraftState;
29  import org.orekit.propagation.SpacecraftStateInterpolator;
30  import org.orekit.propagation.covariance.StateCovariance;
31  import org.orekit.propagation.analytical.Ephemeris;
32  import org.orekit.time.TimeInterpolator;
33  import org.orekit.time.TimeStampedPair;
34  import org.orekit.utils.ParameterDriversList;
35  
36  import java.util.ArrayList;
37  import java.util.List;
38  
39  /**
40   * Builder for Ephemeris propagator.
41   *
42   * @author Bryan Cazabonne
43   * @author Vincent Cucchietti
44   * @since 11.3
45   */
46  public class EphemerisPropagatorBuilder
47      extends AbstractPropagatorBuilder<Ephemeris, Orbit, AbstractOrbitFactory<Orbit>> {
48  
49      /** Default position scale (not used for ephemeris based estimation). */
50      private static final double DEFAULT_SCALE = 10.0;
51  
52      /** List of spacecraft states. */
53      private final List<SpacecraftState> states;
54  
55      /** List of covariances. **/
56      private final List<StateCovariance> covariances;
57  
58      /** Spacecraft state interpolator. */
59      private final TimeInterpolator<SpacecraftState> stateInterpolator;
60  
61      /** State covariance interpolator. */
62      private final TimeInterpolator<TimeStampedPair<Orbit, StateCovariance>> covarianceInterpolator;
63  
64      /** Attitude provider. */
65      private final AttitudeProvider provider;
66  
67      /**
68       * Constructor using the default attitude provider.
69       * <p>
70       * The default attitude provider is an {@link org.orekit.attitudes.FrameAlignedProvider inertial provider} built from the frame of the first
71       * spacecraft state instance in given list
72       *
73       * @param states list of spacecraft states
74       * @param stateInterpolator spacecraft state interpolator
75       */
76      public EphemerisPropagatorBuilder(final List<SpacecraftState> states,
77                                        final TimeInterpolator<SpacecraftState> stateInterpolator) {
78          this(states, stateInterpolator, states.isEmpty() ? null : new FrameAlignedProvider(states.getFirst().getFrame()));
79      }
80  
81      /**
82       * Constructor.
83       *
84       * @param states list of spacecraft states
85       * @param stateInterpolator spacecraft state interpolator
86       * @param attitudeProvider attitude law to use
87       */
88      public EphemerisPropagatorBuilder(final List<SpacecraftState> states,
89                                        final TimeInterpolator<SpacecraftState> stateInterpolator,
90                                        final AttitudeProvider attitudeProvider) {
91          this(states, stateInterpolator, new ArrayList<>(), null, attitudeProvider);
92      }
93  
94      /**
95       * Constructor.
96       *
97       * @param states list of spacecraft states
98       * @param interpolationPoints number of interpolation points
99       * @param extrapolationThreshold extrapolation threshold beyond which the propagation will fail
100      * @param attitudeProvider attitude law to use
101      */
102     public EphemerisPropagatorBuilder(final List<SpacecraftState> states,
103                                       final int interpolationPoints,
104                                       final double extrapolationThreshold,
105                                       final AttitudeProvider attitudeProvider) {
106         this(states,
107              new SpacecraftStateInterpolator(interpolationPoints, extrapolationThreshold,
108                                              states.getFirst().getFrame(), states.getFirst().getFrame()),
109              attitudeProvider);
110     }
111 
112     /**
113      * Constructor with covariances and default attitude provider.
114      * <p>
115      * The default attitude provider is an {@link FrameAlignedProvider inertial provider} built from the frame of the first
116      * spacecraft state instance in given list
117      *
118      * @param states list of spacecraft states
119      * @param stateInterpolator spacecraft state interpolator
120      * @param covariances tabulated covariances associated to tabulated states
121      * @param covarianceInterpolator covariance interpolator
122      *
123      * @see StateCovariance
124      * @see FrameAlignedProvider
125      */
126     public EphemerisPropagatorBuilder(final List<SpacecraftState> states,
127                                       final TimeInterpolator<SpacecraftState> stateInterpolator,
128                                       final List<StateCovariance> covariances,
129                                       final TimeInterpolator<TimeStampedPair<Orbit, StateCovariance>> covarianceInterpolator) {
130         this(states, stateInterpolator, covariances, covarianceInterpolator,
131              states.isEmpty() ? null : new FrameAlignedProvider(states.getFirst().getFrame()));
132     }
133 
134     /**
135      * Constructor.
136      *
137      * @param states list of spacecraft states
138      * @param stateInterpolator spacecraft state interpolator
139      * @param covariances tabulated covariances associated to tabulated states
140      * @param covarianceInterpolator covariance interpolator
141      * @param attitudeProvider attitude law to use
142      */
143     public EphemerisPropagatorBuilder(final List<SpacecraftState> states,
144                                       final TimeInterpolator<SpacecraftState> stateInterpolator,
145                                       final List<StateCovariance> covariances,
146                                       final TimeInterpolator<TimeStampedPair<Orbit, StateCovariance>> covarianceInterpolator,
147                                       final AttitudeProvider attitudeProvider) {
148         super((AbstractOrbitFactory<Orbit>) states.getFirst().getOrbit().factory(PositionAngleType.TRUE, DEFAULT_SCALE),
149               false, attitudeProvider);
150         deselectDynamicParameters();
151 
152         // Check input consistency the same way Ephemeris is checking consistency
153         Ephemeris.checkInputConsistency(states, stateInterpolator, covariances, covarianceInterpolator);
154 
155         this.states                 = states;
156         this.stateInterpolator      = stateInterpolator;
157         this.covariances            = covariances == null ? new ArrayList<>() : covariances;
158         this.covarianceInterpolator = covarianceInterpolator;
159         this.provider               = attitudeProvider;
160     }
161 
162     /** Copy constructor.
163      * @param builder builder to copy from
164      */
165     private EphemerisPropagatorBuilder(final EphemerisPropagatorBuilder builder) {
166         this(builder.states, builder.stateInterpolator, builder.covariances,
167              builder.covarianceInterpolator, builder.getAttitudeProvider());
168     }
169 
170     /** {@inheritDoc}. */
171     @Override
172     public EphemerisPropagatorBuilder clone() {
173         // Call to super clone() method to avoid warning
174         final EphemerisPropagatorBuilder clonedBuilder = (EphemerisPropagatorBuilder) super.clone();
175 
176         // Use copy constructor to unlink orbital drivers
177         final EphemerisPropagatorBuilder builder = new EphemerisPropagatorBuilder(clonedBuilder);
178 
179         // Set mass
180         builder.setMass(getMass());
181 
182         // Return cloned builder
183         return builder;
184     }
185 
186     /** {@inheritDoc}. */
187     @Override
188     public Ephemeris buildPropagator(final double[] normalizedParameters) {
189         if (!covariances.isEmpty() && covarianceInterpolator != null) {
190             return new Ephemeris(states, stateInterpolator, covariances, covarianceInterpolator, provider);
191         }
192         return new Ephemeris(states, stateInterpolator, provider);
193 
194     }
195 
196     /** {@inheritDoc} */
197     @Override
198     public AbstractBatchLSModel buildLeastSquaresModel(final PropagatorBuilder[] builders,
199                                                        final List<ObservedMeasurement<?>> measurements,
200                                                        final ParameterDriversList estimatedMeasurementsParameters,
201                                                        final ModelObserver observer) {
202         return new BatchLSModel(builders, measurements, estimatedMeasurementsParameters, observer);
203     }
204 
205 }