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.analytical;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.hipparchus.analysis.differentiation.Gradient;
23  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24  import org.hipparchus.geometry.euclidean.threed.Vector3D;
25  import org.orekit.attitudes.AttitudeProvider;
26  import org.orekit.attitudes.FieldAttitude;
27  import org.orekit.orbits.FieldCartesianOrbit;
28  import org.orekit.orbits.FieldOrbit;
29  import org.orekit.propagation.FieldSpacecraftState;
30  import org.orekit.propagation.SpacecraftState;
31  import org.orekit.propagation.integration.AbstractGradientConverter;
32  import org.orekit.utils.FieldAngularCoordinates;
33  import org.orekit.utils.FieldPVCoordinates;
34  import org.orekit.utils.ParameterDriver;
35  import org.orekit.utils.ParameterDriversProvider;
36  import org.orekit.utils.TimeStampedFieldAngularCoordinates;
37  import org.orekit.utils.TimeStampedFieldPVCoordinates;
38  
39  /**
40   * Converter for analytical orbit propagator.
41   *
42   * @author Bryan Cazabonne
43   * @since 11.1
44   */
45  public abstract class AbstractAnalyticalGradientConverter extends AbstractGradientConverter implements ParameterDriversProvider {
46  
47      /** Attitude provider. */
48      private final AttitudeProvider provider;
49  
50      /** States with various number of additional propagation parameters. */
51      private final List<FieldSpacecraftState<Gradient>> gStates;
52  
53      /**
54       * Constructor.
55       * @param propagator analytical orbit propagator
56       * @param mu central attraction coefficient
57       * @param freeStateParameters number of free parameters
58       */
59      protected AbstractAnalyticalGradientConverter(final AbstractAnalyticalPropagator propagator,
60                                                    final double mu,
61                                                    final int freeStateParameters) {
62          super(freeStateParameters);
63  
64          // Attitude provider
65          this.provider = propagator.getAttitudeProvider();
66  
67          // Spacecraft state
68          final SpacecraftState state = propagator.getInitialState();
69  
70          // Position always has derivatives
71          final Vector3D pos = state.getPosition();
72          final FieldVector3D<Gradient> posG = new FieldVector3D<>(Gradient.variable(freeStateParameters, 0, pos.getX()),
73                                                                   Gradient.variable(freeStateParameters, 1, pos.getY()),
74                                                                   Gradient.variable(freeStateParameters, 2, pos.getZ()));
75  
76          // Velocity may have derivatives or not
77          final Vector3D vel = state.getPVCoordinates().getVelocity();
78          final FieldVector3D<Gradient> velG = new FieldVector3D<>(Gradient.variable(freeStateParameters, 3, vel.getX()),
79                                                                   Gradient.variable(freeStateParameters, 4, vel.getY()),
80                                                                   Gradient.variable(freeStateParameters, 5, vel.getZ()));
81  
82          // Acceleration never has derivatives
83          final Vector3D acc = state.getPVCoordinates().getAcceleration();
84          final FieldVector3D<Gradient> accG = new FieldVector3D<>(Gradient.constant(freeStateParameters, acc.getX()),
85                                                                   Gradient.constant(freeStateParameters, acc.getY()),
86                                                                   Gradient.constant(freeStateParameters, acc.getZ()));
87  
88          // Mass never has derivatives
89          final Gradient gM  = Gradient.constant(freeStateParameters, state.getMass());
90          final Gradient gMu = Gradient.constant(freeStateParameters, mu);
91  
92          final FieldOrbit<Gradient> gOrbit =
93                          new FieldCartesianOrbit<>(new TimeStampedFieldPVCoordinates<>(state.getDate(), posG, velG, accG),
94                                                    state.getFrame(), gMu);
95  
96          // Attitude
97          final FieldAttitude<Gradient> gAttitude = provider.getAttitude(gOrbit, gOrbit.getDate(), gOrbit.getFrame());
98  
99          // Initialize the list with the state having 0 force model parameters
100         gStates = new ArrayList<>();
101         gStates.add(new FieldSpacecraftState<>(gOrbit, gAttitude, gM));
102 
103     }
104 
105     /** Get the state with the number of parameters consistent with the propagation model.
106      * @return state with the number of parameters consistent with the propagation model
107      */
108     public FieldSpacecraftState<Gradient> getState() {
109 
110         // Count the required number of parameters
111         int nbParams = 0;
112         for (final ParameterDriver driver : getParametersDrivers()) {
113             if (driver.isSelected()) {
114                 ++nbParams;
115             }
116         }
117 
118         // Fill in intermediate slots
119         while (gStates.size() < nbParams + 1) {
120             gStates.add(null);
121         }
122 
123         if (gStates.get(nbParams) == null) {
124             // It is the first time we need this number of parameters
125             // We need to create the state
126             final int freeParameters = getFreeStateParameters() + nbParams;
127             final FieldSpacecraftState<Gradient> s0 = gStates.get(0);
128 
129             // Orbit
130             final FieldPVCoordinates<Gradient> pv0 = s0.getPVCoordinates();
131             final FieldOrbit<Gradient> gOrbit =
132                             new FieldCartesianOrbit<>(new TimeStampedFieldPVCoordinates<>(s0.getDate().toAbsoluteDate(),
133                                                                                           extend(pv0.getPosition(),     freeParameters),
134                                                                                           extend(pv0.getVelocity(),     freeParameters),
135                                                                                           extend(pv0.getAcceleration(), freeParameters)),
136                                                       s0.getFrame(),
137                                                       extend(s0.getMu(), freeParameters));
138 
139             // Attitude
140             final FieldAngularCoordinates<Gradient> ac0 = s0.getAttitude().getOrientation();
141             final FieldAttitude<Gradient> gAttitude =
142                             new FieldAttitude<>(s0.getAttitude().getReferenceFrame(),
143                                                 new TimeStampedFieldAngularCoordinates<>(gOrbit.getDate(),
144                                                                                          extend(ac0.getRotation(), freeParameters),
145                                                                                          extend(ac0.getRotationRate(), freeParameters),
146                                                                                          extend(ac0.getRotationAcceleration(), freeParameters)));
147 
148             // Mass
149             final Gradient gM = extend(s0.getMass(), freeParameters);
150 
151             gStates.set(nbParams, new FieldSpacecraftState<>(gOrbit, gAttitude, gM));
152         }
153 
154         return gStates.get(nbParams);
155     }
156 
157     /**
158      * Get the converted analytical orbit propagator.
159      * @param state state as returned by {@link #getState()}
160      * @param parameters model parameters
161      * @return the converted analytical orbit propagator
162      */
163     public abstract FieldAbstractAnalyticalPropagator<Gradient> getPropagator(FieldSpacecraftState<Gradient> state,
164                                                                               Gradient[] parameters);
165 
166 }