1   /* Copyright 2002-2021 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.semianalytical.dsst;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.hipparchus.analysis.differentiation.Gradient;
23  import org.hipparchus.analysis.differentiation.GradientField;
24  import org.orekit.attitudes.AttitudeProvider;
25  import org.orekit.attitudes.FieldAttitude;
26  import org.orekit.orbits.FieldEquinoctialOrbit;
27  import org.orekit.orbits.FieldOrbit;
28  import org.orekit.orbits.PositionAngle;
29  import org.orekit.propagation.FieldSpacecraftState;
30  import org.orekit.propagation.SpacecraftState;
31  import org.orekit.propagation.integration.AbstractGradientConverter;
32  import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
33  import org.orekit.time.AbsoluteDate;
34  import org.orekit.time.FieldAbsoluteDate;
35  import org.orekit.utils.FieldAngularCoordinates;
36  import org.orekit.utils.ParameterDriver;
37  import org.orekit.utils.TimeStampedFieldAngularCoordinates;
38  
39  /** Converter for states and parameters arrays.
40   * @author Luc Maisonobe
41   * @author Bryan Cazabonne
42   * @since 10.2
43   */
44  class DSSTGradientConverter extends AbstractGradientConverter {
45  
46      /** Fixed dimension of the state. */
47      private static final int FREE_STATE_PARAMETERS = 6;
48  
49      /** States with various number of additional parameters for force models. */
50      private final List<FieldSpacecraftState<Gradient>> gStates;
51  
52      /** Simple constructor.
53       * @param state regular state
54       * @param provider provider to use if attitude needs to be recomputed
55       */
56      DSSTGradientConverter(final SpacecraftState state, final AttitudeProvider provider) {
57  
58          super(FREE_STATE_PARAMETERS);
59  
60          // equinoctial parameters always has derivatives
61          final Gradient sma  = Gradient.variable(FREE_STATE_PARAMETERS, 0, state.getA());
62          final Gradient ex   = Gradient.variable(FREE_STATE_PARAMETERS, 1, state.getEquinoctialEx());
63          final Gradient ey   = Gradient.variable(FREE_STATE_PARAMETERS, 2, state.getEquinoctialEy());
64          final Gradient hx   = Gradient.variable(FREE_STATE_PARAMETERS, 3, state.getHx());
65          final Gradient hy   = Gradient.variable(FREE_STATE_PARAMETERS, 4, state.getHy());
66          final Gradient l    = Gradient.variable(FREE_STATE_PARAMETERS, 5, state.getLM());
67  
68          final Gradient gMu = Gradient.constant(FREE_STATE_PARAMETERS, state.getMu());
69  
70          // date
71          final AbsoluteDate date = state.getDate();
72          final FieldAbsoluteDate<Gradient> dateField = new FieldAbsoluteDate<>(sma.getField(), date);
73  
74          // mass never has derivatives
75          final Gradient gM = Gradient.constant(FREE_STATE_PARAMETERS, state.getMass());
76  
77          final FieldOrbit<Gradient> gOrbit =
78                          new FieldEquinoctialOrbit<>(sma, ex, ey, hx, hy, l,
79                                                      PositionAngle.MEAN,
80                                                      state.getFrame(),
81                                                      dateField,
82                                                      gMu);
83  
84          final FieldAttitude<Gradient> gAttitude;
85          // compute attitude partial derivatives
86          gAttitude = provider.getAttitude(gOrbit, gOrbit.getDate(), gOrbit.getFrame());
87  
88          // initialize the list with the state having 0 force model parameters
89          gStates = new ArrayList<>();
90          gStates.add(new FieldSpacecraftState<>(gOrbit, gAttitude, gM));
91  
92      }
93  
94      /** Get the state with the number of parameters consistent with force model.
95       * @param forceModel force model
96       * @return state with the number of parameters consistent with force model
97       */
98      public FieldSpacecraftState<Gradient> getState(final DSSTForceModel forceModel) {
99  
100         // count the required number of parameters
101         int nbParams = 0;
102         for (final ParameterDriver driver : forceModel.getParametersDrivers()) {
103             if (driver.isSelected()) {
104                 ++nbParams;
105             }
106         }
107 
108         // fill in intermediate slots
109         while (gStates.size() < nbParams + 1) {
110             gStates.add(null);
111         }
112 
113         if (gStates.get(nbParams) == null) {
114             // it is the first time we need this number of parameters
115             // we need to create the state
116             final int freeParameters = FREE_STATE_PARAMETERS + nbParams;
117             final FieldSpacecraftState<Gradient> s0 = gStates.get(0);
118 
119             final FieldAbsoluteDate<Gradient> date = new FieldAbsoluteDate<>(GradientField.getField(freeParameters),
120                                                                              s0.getDate().toAbsoluteDate());
121             // orbit
122             final FieldOrbit<Gradient> gOrbit =
123                             new FieldEquinoctialOrbit<>(extend(s0.getA(),             freeParameters),
124                                                         extend(s0.getEquinoctialEx(), freeParameters),
125                                                         extend(s0.getEquinoctialEy(), freeParameters),
126                                                         extend(s0.getHx(),            freeParameters),
127                                                         extend(s0.getHy(),            freeParameters),
128                                                         extend(s0.getLM(),            freeParameters),
129                                                         PositionAngle.MEAN,
130                                                         s0.getFrame(), date,
131                                                         extend(s0.getMu(),            freeParameters));
132 
133             // attitude
134             final FieldAngularCoordinates<Gradient> ac0 = s0.getAttitude().getOrientation();
135             final FieldAttitude<Gradient> gAttitude =
136                             new FieldAttitude<>(s0.getAttitude().getReferenceFrame(),
137                                                 new TimeStampedFieldAngularCoordinates<>(gOrbit.getDate(),
138                                                                                          extend(ac0.getRotation(),             freeParameters),
139                                                                                          extend(ac0.getRotationRate(),         freeParameters),
140                                                                                          extend(ac0.getRotationAcceleration(), freeParameters)));
141 
142             // mass
143             final Gradient gM = extend(s0.getMass(), freeParameters);
144 
145             gStates.set(nbParams, new FieldSpacecraftState<>(gOrbit, gAttitude, gM));
146 
147         }
148 
149         return gStates.get(nbParams);
150 
151     }
152 
153     /** Get the force model parameters.
154      * @param state state as returned by {@link #getState(DSSTForceModel)}
155      * @param forceModel force model associated with the parameters
156      * @return force model parameters
157      */
158     public Gradient[] getParameters(final FieldSpacecraftState<Gradient> state,
159                                     final DSSTForceModel forceModel) {
160         final int freeParameters = state.getA().getFreeParameters();
161         final List<ParameterDriver> drivers = forceModel.getParametersDrivers();
162         final Gradient[] parameters = new Gradient[drivers.size()];
163         int index = FREE_STATE_PARAMETERS;
164         int i = 0;
165         for (ParameterDriver driver : drivers) {
166             parameters[i++] = driver.isSelected() ?
167                               Gradient.variable(freeParameters, index++, driver.getValue()) :
168                               Gradient.constant(freeParameters, driver.getValue());
169         }
170         return parameters;
171     }
172 
173 }