1   /* Copyright 2002-2022 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.List;
20  
21  import org.orekit.attitudes.AttitudeProvider;
22  import org.orekit.attitudes.InertialProvider;
23  import org.orekit.estimation.leastsquares.AbstractBatchLSModel;
24  import org.orekit.estimation.leastsquares.BatchLSModel;
25  import org.orekit.estimation.leastsquares.ModelObserver;
26  import org.orekit.estimation.measurements.ObservedMeasurement;
27  import org.orekit.estimation.sequential.AbstractKalmanModel;
28  import org.orekit.estimation.sequential.CovarianceMatrixProvider;
29  import org.orekit.estimation.sequential.KalmanModel;
30  import org.orekit.forces.gravity.potential.GravityFieldFactory;
31  import org.orekit.forces.gravity.potential.TideSystem;
32  import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
33  import org.orekit.orbits.Orbit;
34  import org.orekit.orbits.OrbitType;
35  import org.orekit.orbits.PositionAngle;
36  import org.orekit.propagation.Propagator;
37  import org.orekit.propagation.analytical.EcksteinHechlerPropagator;
38  import org.orekit.utils.ParameterDriversList;
39  
40  /** Builder for Eckstein-Hechler propagator.
41   * @author Pascal Parraud
42   * @since 6.0
43   */
44  public class EcksteinHechlerPropagatorBuilder extends AbstractPropagatorBuilder implements OrbitDeterminationPropagatorBuilder {
45  
46      /** Provider for un-normalized coefficients. */
47      private final UnnormalizedSphericalHarmonicsProvider provider;
48  
49      /** Build a new instance.
50       * <p>
51       * The template orbit is used as a model to {@link
52       * #createInitialOrbit() create initial orbit}. It defines the
53       * inertial frame, the central attraction coefficient, the orbit type, and is also
54       * used together with the {@code positionScale} to convert from the {@link
55       * org.orekit.utils.ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
56       * callers of this builder to the real orbital parameters.
57       * </p>
58       *
59       * @param templateOrbit reference orbit from which real orbits will be built
60       * (note that the mu from this orbit will be overridden with the mu from the
61       * {@code provider})
62       * @param provider for un-normalized zonal coefficients
63       * @param positionAngle position angle type to use
64       * @param positionScale scaling factor used for orbital parameters normalization
65       * (typically set to the expected standard deviation of the position)
66       * @since 8.0
67       * @see #EcksteinHechlerPropagatorBuilder(Orbit,
68       * UnnormalizedSphericalHarmonicsProvider, PositionAngle, double, AttitudeProvider)
69       */
70      public EcksteinHechlerPropagatorBuilder(final Orbit templateOrbit,
71                                              final UnnormalizedSphericalHarmonicsProvider provider,
72                                              final PositionAngle positionAngle,
73                                              final double positionScale) {
74          this(templateOrbit, provider, positionAngle, positionScale,
75                  InertialProvider.of(templateOrbit.getFrame()));
76      }
77  
78      /** Build a new instance.
79       * <p>
80       * The template orbit is used as a model to {@link
81       * #createInitialOrbit() create initial orbit}. It defines the
82       * inertial frame, the central attraction coefficient, the orbit type, and is also
83       * used together with the {@code positionScale} to convert from the {@link
84       * org.orekit.utils.ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
85       * callers of this builder to the real orbital parameters.
86       * </p>
87       * @param templateOrbit reference orbit from which real orbits will be built
88       * (note that the mu from this orbit will be overridden with the mu from the
89       * {@code provider})
90       * @param provider for un-normalized zonal coefficients
91       * @param positionAngle position angle type to use
92       * @param positionScale scaling factor used for orbital parameters normalization
93       * (typically set to the expected standard deviation of the position)
94       * @param attitudeProvider attitude law to use.
95       * @since 10.1
96       */
97      public EcksteinHechlerPropagatorBuilder(final Orbit templateOrbit,
98                                              final UnnormalizedSphericalHarmonicsProvider provider,
99                                              final PositionAngle positionAngle,
100                                             final double positionScale,
101                                             final AttitudeProvider attitudeProvider) {
102         super(overrideMu(templateOrbit, provider, positionAngle), positionAngle,
103                 positionScale, true, attitudeProvider);
104         this.provider = provider;
105     }
106 
107     /** Build a new instance.
108      * <p>
109      * The template orbit is used as a model to {@link
110      * #createInitialOrbit() create initial orbit}. It defines the
111      * inertial frame, the central attraction coefficient, the orbit type, and is also
112      * used together with the {@code positionScale} to convert from the {@link
113      * org.orekit.utils.ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
114      * callers of this builder to the real orbital parameters.
115      * </p>
116      *
117      * @param templateOrbit reference orbit from which real orbits will be built
118      * (note that the mu from this orbit will be overridden with the mu from the
119      * {@code provider})
120      * @param referenceRadius reference radius of the Earth for the potential model (m)
121      * @param mu central attraction coefficient (m³/s²)
122      * @param tideSystem tide system
123      * @param c20 un-normalized zonal coefficient (about -1.08e-3 for Earth)
124      * @param c30 un-normalized zonal coefficient (about +2.53e-6 for Earth)
125      * @param c40 un-normalized zonal coefficient (about +1.62e-6 for Earth)
126      * @param c50 un-normalized zonal coefficient (about +2.28e-7 for Earth)
127      * @param c60 un-normalized zonal coefficient (about -5.41e-7 for Earth)
128      * @param orbitType orbit type to use
129      * @param positionAngle position angle type to use
130      * @param positionScale scaling factor used for orbital parameters normalization
131      * (typically set to the expected standard deviation of the position)
132      * @since 8.0
133      * @see #EcksteinHechlerPropagatorBuilder(Orbit,
134      * UnnormalizedSphericalHarmonicsProvider, PositionAngle, double, AttitudeProvider)
135      */
136     public EcksteinHechlerPropagatorBuilder(final Orbit templateOrbit,
137                                             final double referenceRadius,
138                                             final double mu,
139                                             final TideSystem tideSystem,
140                                             final double c20,
141                                             final double c30,
142                                             final double c40,
143                                             final double c50,
144                                             final double c60,
145                                             final OrbitType orbitType,
146                                             final PositionAngle positionAngle,
147                                             final double positionScale) {
148         this(templateOrbit,
149              GravityFieldFactory.getUnnormalizedProvider(referenceRadius, mu, tideSystem,
150                                                          new double[][] {
151                                                              {
152                                                                  0
153                                                              }, {
154                                                                  0
155                                                              }, {
156                                                                  c20
157                                                              }, {
158                                                                  c30
159                                                              }, {
160                                                                  c40
161                                                              }, {
162                                                                  c50
163                                                              }, {
164                                                                  c60
165                                                              }
166                                                          }, new double[][] {
167                                                              {
168                                                                  0
169                                                              }, {
170                                                                  0
171                                                              }, {
172                                                                  0
173                                                              }, {
174                                                                  0
175                                                              }, {
176                                                                  0
177                                                              }, {
178                                                                  0
179                                                              }, {
180                                                                  0
181                                                              }
182                                                          }),
183              positionAngle, positionScale);
184     }
185 
186     /** Override central attraction coefficient.
187      * @param templateOrbit template orbit
188      * @param provider gravity field provider
189      * @param positionAngle position angle type to use
190      * @return orbit with overridden central attraction coefficient
191      */
192     private static Orbit overrideMu(final Orbit templateOrbit,
193                                     final UnnormalizedSphericalHarmonicsProvider provider,
194                                     final PositionAngle positionAngle) {
195         final double[] parameters    = new double[6];
196         final double[] parametersDot = templateOrbit.hasDerivatives() ? new double[6] : null;
197         templateOrbit.getType().mapOrbitToArray(templateOrbit, positionAngle, parameters, parametersDot);
198         return templateOrbit.getType().mapArrayToOrbit(parameters, parametersDot, positionAngle,
199                                                        templateOrbit.getDate(),
200                                                        provider.getMu(),
201                                                        templateOrbit.getFrame());
202     }
203 
204     /** {@inheritDoc} */
205     public Propagator buildPropagator(final double[] normalizedParameters) {
206         setParameters(normalizedParameters);
207         return new EcksteinHechlerPropagator(createInitialOrbit(), getAttitudeProvider(),
208                 provider);
209     }
210 
211     /** {@inheritDoc} */
212     @Override
213     public AbstractBatchLSModel buildLSModel(final OrbitDeterminationPropagatorBuilder[] builders,
214                                              final List<ObservedMeasurement<?>> measurements,
215                                              final ParameterDriversList estimatedMeasurementsParameters,
216                                              final ModelObserver observer) {
217         return new BatchLSModel(builders, measurements, estimatedMeasurementsParameters, observer);
218     }
219 
220     /** {@inheritDoc} */
221     @Override
222     public AbstractKalmanModel buildKalmanModel(final List<OrbitDeterminationPropagatorBuilder> propagatorBuilders,
223                                                 final List<CovarianceMatrixProvider> covarianceMatricesProviders,
224                                                 final ParameterDriversList estimatedMeasurementsParameters,
225                                                 final CovarianceMatrixProvider measurementProcessNoiseMatrix) {
226         return new KalmanModel(propagatorBuilders, covarianceMatricesProviders, estimatedMeasurementsParameters, measurementProcessNoiseMatrix);
227     }
228 
229 }