1   /* Copyright 2020-2025 Exotrail
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.averaging.converters;
18  
19  import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
20  import org.orekit.orbits.KeplerianOrbit;
21  import org.orekit.orbits.Orbit;
22  import org.orekit.propagation.analytical.BrouwerLyddanePropagator;
23  import org.orekit.propagation.conversion.averaging.BrouwerLyddaneOrbitalState;
24  import org.orekit.propagation.conversion.averaging.elements.AveragedKeplerianWithMeanAngle;
25  
26  /**
27   * Class for osculating-to-averaged conversion according to Brouwer-Lyddane theory.
28   * Value of M2 parameter is set to zero.
29   *
30   * @author Romain Serra
31   * @see BrouwerLyddanePropagator
32   * @see BrouwerLyddaneOrbitalState
33   * @since 12.1
34   */
35  public class OsculatingToBrouwerLyddaneConverter
36          extends FixedPointOsculatingToAveragedConverter<BrouwerLyddaneOrbitalState> {
37  
38      /** So-called M2 coefficient, set to zero. */
39      private static final double M2 = 0.;
40      /** Order for spherical harmonics. */
41      private static final int HARMONICS_ORDER = 0;
42  
43      /** Spherical harmonics provider. */
44      private final UnnormalizedSphericalHarmonicsProvider harmonicsProvider;
45  
46      /**
47       * Constructor with default parameters for fixed-point algorithm.
48       * @param harmonicsProvider unnormalized provider
49       */
50      public OsculatingToBrouwerLyddaneConverter(final UnnormalizedSphericalHarmonicsProvider harmonicsProvider) {
51          this(DEFAULT_EPSILON, DEFAULT_MAX_ITERATIONS, harmonicsProvider);
52      }
53  
54      /**
55       * Constructor.
56       * @param epsilon convergence threshold
57       * @param maxIterations maximum number of iterations
58       * @param harmonicsProvider unnormalized provider
59       */
60      public OsculatingToBrouwerLyddaneConverter(final double epsilon, final int maxIterations,
61                                                 final UnnormalizedSphericalHarmonicsProvider harmonicsProvider) {
62          super(epsilon, maxIterations);
63          this.harmonicsProvider = harmonicsProvider;
64      }
65  
66      /** {@inheritDoc} */
67      @Override
68      public BrouwerLyddaneOrbitalState convertToAveraged(final Orbit osculatingOrbit) {
69          final KeplerianOrbit averagedOrbit = createAveragedOrbit(osculatingOrbit);
70          final AveragedKeplerianWithMeanAngle averagedElements = buildElements(averagedOrbit);
71          return new BrouwerLyddaneOrbitalState(averagedOrbit.getDate(), averagedElements,
72                  averagedOrbit.getFrame(), harmonicsProvider);
73      }
74  
75      /**
76       * Build averaged orbit.
77       * @param osculatingOrbit osculating orbit
78       * @return averaged Keplerian orbit in Brouwer-Lyddane sense.
79       */
80      private KeplerianOrbit createAveragedOrbit(final Orbit osculatingOrbit) {
81          final UnnormalizedSphericalHarmonicsProvider.UnnormalizedSphericalHarmonics harmonics =
82                  harmonicsProvider.onDate(osculatingOrbit.getDate());
83          return BrouwerLyddanePropagator.computeMeanOrbit(osculatingOrbit,
84                  harmonicsProvider.getAe(), harmonicsProvider.getMu(),
85                  harmonics.getUnnormalizedCnm(2, HARMONICS_ORDER),
86                  harmonics.getUnnormalizedCnm(3, HARMONICS_ORDER),
87                  harmonics.getUnnormalizedCnm(4, HARMONICS_ORDER),
88                  harmonics.getUnnormalizedCnm(5, HARMONICS_ORDER),
89                  M2, getEpsilon(), getMaxIterations());
90      }
91  
92      /**
93       * Build averaged orbital elements from orbit.
94       * @param averagedOrbit averaged orbit
95       * @return orbital elements
96       */
97      private AveragedKeplerianWithMeanAngle buildElements(final KeplerianOrbit averagedOrbit) {
98          return new AveragedKeplerianWithMeanAngle(averagedOrbit.getA(), averagedOrbit.getE(),
99                  averagedOrbit.getI(), averagedOrbit.getPerigeeArgument(),
100                 averagedOrbit.getRightAscensionOfAscendingNode(), averagedOrbit.getMeanAnomaly());
101     }
102 
103 }