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