GnssGradientConverter.java
/* Copyright 2022-2026 Luc Maisonobe
* Licensed to CS GROUP (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.propagation.analytical.gnss;
import org.hipparchus.analysis.differentiation.Gradient;
import org.orekit.orbits.FieldKeplerianOrbit;
import org.orekit.orbits.OrbitType;
import org.orekit.propagation.FieldSpacecraftState;
import org.orekit.propagation.analytical.AbstractAnalyticalGradientConverter;
import org.orekit.propagation.analytical.gnss.data.FieldGnssOrbitalElements;
import org.orekit.propagation.analytical.gnss.data.GNSSOrbitalElements;
import org.orekit.propagation.analytical.gnss.data.NonKeplerianDriversFactory;
import org.orekit.utils.ParameterDriver;
import java.util.List;
/** Converter for GNSS propagator.
* @param <O> type of the orbital elements (non-field version)
* @author Luc Maisonobe
* @since 13.0
*/
class GnssGradientConverter<O extends GNSSOrbitalElements<O>>
extends AbstractAnalyticalGradientConverter {
/** Fixed dimension of the state. */
public static final int FREE_STATE_PARAMETERS = 6;
/** Orbit propagator. */
private final GNSSPropagator<O> propagator;
/** Simple constructor.
* @param propagator orbit propagator used to access initial orbit
*/
GnssGradientConverter(final GNSSPropagator<O> propagator) {
super(propagator, FREE_STATE_PARAMETERS);
this.propagator = propagator;
}
/** {@inheritDoc}
* <p>
* The free variables of the returned gradients are the six <em>Cartesian</em> coordinates
* of the initial state, extended with one slot per selected non-Keplerian driver. The
* state transition matrix built from this propagator is therefore a genuine dY/dY₀, with
* the same representation for its rows and its columns, consistent with
* {@link org.orekit.propagation.analytical.AbstractAnalyticalMatricesHarvester#getOrbitType()}
* returning {@link OrbitType#CARTESIAN}. The change of representation towards the
* propagator builder parameters is a separate quantity, provided by
* {@link org.orekit.propagation.analytical.gnss.data.GNSSOrbitalElementsFactory#jacobianWrtParameters}.
* </p>
*/
@Override
public FieldGnssPropagator<Gradient, O> getPropagator() {
// Cartesian state whose coordinates are the free variables of the gradients
final FieldSpacecraftState<Gradient> gState = getState(this);
final int nbParams = gState.getMass().getFreeParameters();
// Keplerian view of that very state; the conversion carries the derivatives along,
// so the free variables remain the Cartesian coordinates
final FieldKeplerianOrbit<Gradient> gOrbit =
(FieldKeplerianOrbit<Gradient>) OrbitType.KEPLERIAN.convertType(gState.getOrbit());
// prepare non-Keplerian elements with proper derivatives
final Gradient[] parameters = propagator.getDriversFactory().toGradients(nbParams);
// convert elements to support gradient
final FieldGnssOrbitalElements<Gradient, O> nonKeplerian =
propagator.getOrbitalElements().toField(gOrbit, parameters, d -> Gradient.constant(nbParams, d));
final FieldGnssOrbitalElements<Gradient, O> gElements =
FieldGnssPropagator.buildOrbitalElements(gState, nonKeplerian,
new NonKeplerianDriversFactory(),
propagator.getECEF(),
propagator.getAttitudeProvider(),
gState.getMass());
// build propagator handling gradient
final FieldGnssPropagator<Gradient, O> gPropagator =
new FieldGnssPropagator<>(gElements, gState.getFrame(),
propagator.getECEF(), propagator.getAttitudeProvider(),
gState.getMass());
final List<ParameterDriver> gDrivers = gPropagator.getParametersDrivers();
for (final ParameterDriver driver : getParametersDrivers()) {
if (driver.isSelected()) {
gDrivers.
stream().
filter(gDriver -> driver.getName().equals(gDriver.getName())).
findFirst().
ifPresent(gDriver -> gDriver.setSelected(true));
}
}
return gPropagator;
}
/** {@inheritDoc} */
@Override
public List<ParameterDriver> getParametersDrivers() {
return propagator.getParametersDrivers();
}
}