DSSTTheory.java
- /* Copyright 2002-2025 CS GROUP
- * 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.conversion.osc2mean;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.List;
- import org.hipparchus.CalculusFieldElement;
- import org.hipparchus.Field;
- import org.hipparchus.util.MathArrays;
- import org.orekit.attitudes.Attitude;
- import org.orekit.attitudes.AttitudeProvider;
- import org.orekit.attitudes.FieldAttitude;
- import org.orekit.attitudes.FrameAlignedProvider;
- import org.orekit.orbits.FieldOrbit;
- import org.orekit.orbits.Orbit;
- import org.orekit.orbits.OrbitType;
- import org.orekit.orbits.PositionAngleType;
- import org.orekit.propagation.FieldSpacecraftState;
- import org.orekit.propagation.PropagationType;
- import org.orekit.propagation.Propagator;
- import org.orekit.propagation.SpacecraftState;
- import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
- import org.orekit.propagation.semianalytical.dsst.forces.FieldShortPeriodTerms;
- import org.orekit.propagation.semianalytical.dsst.forces.ShortPeriodTerms;
- import org.orekit.propagation.semianalytical.dsst.utilities.AuxiliaryElements;
- import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;
- import org.orekit.time.FieldAbsoluteDate;
- import org.orekit.utils.Constants;
- /**
- * DSST theory for osculating to mean orbit conversion.
- *
- * @author Pascal Parraud
- * @since 13.0
- */
- public class DSSTTheory implements MeanTheory {
- /** Theory used for converting from osculating to mean orbit. */
- public static final String THEORY = "DSST";
- /** Force models used to compute short periodic terms. */
- private final Collection<DSSTForceModel> forceModels;
- /** Spacecraft mass (kg). */
- private final double mass;
- /** Attitude provider. */
- private AttitudeProvider attitudeProvider;
- /**
- * Constructor with default values.
- * @param forceModels the force models
- */
- public DSSTTheory(final Collection<DSSTForceModel> forceModels) {
- this(forceModels, null, Propagator.DEFAULT_MASS);
- }
- /**
- * Full constructor.
- * @param forceModels the force models
- * @param attitudeProvider the attitude law
- * @param mass the mass (kg)
- */
- public DSSTTheory(final Collection<DSSTForceModel> forceModels,
- final AttitudeProvider attitudeProvider,
- final double mass) {
- this.forceModels = forceModels;
- this.attitudeProvider = attitudeProvider;
- this.mass = mass;
- }
- /** {@inheritDoc} */
- @Override
- public String getTheoryName() {
- return THEORY;
- }
- /** {@inheritDoc} */
- @Override
- public double getReferenceRadius() {
- return Constants.IERS2010_EARTH_EQUATORIAL_RADIUS;
- };
- /** {@inheritDoc} */
- @Override
- public Orbit preprocessing(final Orbit osculating) {
- // If not defined
- if (attitudeProvider == null) {
- // Creates a default attitude provider
- attitudeProvider = FrameAlignedProvider.of(osculating.getFrame());
- }
- // ensure all Gaussian force models can rely on attitude
- for (final DSSTForceModel force : forceModels) {
- force.registerAttitudeProvider(attitudeProvider);
- }
- // Returns an equinoctial orbit
- return OrbitType.EQUINOCTIAL.convertType(osculating);
- }
- /** {@inheritDoc} */
- @Override
- public Orbit meanToOsculating(final Orbit mean) {
- // Create the spacecraft state
- final Attitude attitude = attitudeProvider.getAttitude(mean, mean.getDate(), mean.getFrame());
- final SpacecraftState meanState = new SpacecraftState(mean, attitude).withMass(mass);
- // Create the auxiliary object
- final AuxiliaryElements aux = new AuxiliaryElements(mean, +1);
- // Set the force models
- final List<ShortPeriodTerms> shortPeriodTerms = new ArrayList<>();
- for (final DSSTForceModel force : forceModels) {
- shortPeriodTerms.addAll(force.initializeShortPeriodTerms(aux, PropagationType.OSCULATING,
- force.getParameters(mean.getDate())));
- force.updateShortPeriodTerms(force.getParametersAllValues(), meanState);
- }
- // recompute the osculating parameters from the current mean parameters
- return computeOsculatingOrbit(mean, shortPeriodTerms);
- }
- /** Compute osculating orbit from mean orbit.
- * <p>
- * Compute and add the short periodic variation to the mean orbit.
- * </p>
- * @param meanOrbit initial mean orbit
- * @param shortPeriodTerms short period terms
- * @return osculating orbit
- */
- private Orbit computeOsculatingOrbit(final Orbit meanOrbit,
- final List<ShortPeriodTerms> shortPeriodTerms) {
- final double[] mean = new double[6];
- final double[] meanDot = new double[6];
- OrbitType.EQUINOCTIAL.mapOrbitToArray(meanOrbit, PositionAngleType.MEAN, mean, meanDot);
- final double[] y = mean.clone();
- for (final ShortPeriodTerms spt : shortPeriodTerms) {
- final double[] shortPeriodic = spt.value(meanOrbit);
- for (int i = 0; i < shortPeriodic.length; i++) {
- y[i] += shortPeriodic[i];
- }
- }
- return OrbitType.EQUINOCTIAL.mapArrayToOrbit(y, meanDot, PositionAngleType.MEAN,
- meanOrbit.getDate(), meanOrbit.getMu(),
- meanOrbit.getFrame());
- }
- /** {@inheritDoc} */
- @Override
- public <T extends CalculusFieldElement<T>> FieldOrbit<T> preprocessing(final FieldOrbit<T> osculating) {
- // If not defined
- if (attitudeProvider == null) {
- // Creates a default attitude provider
- attitudeProvider = FrameAlignedProvider.of(osculating.getFrame());
- }
- // ensure all Gaussian force models can rely on attitude
- for (final DSSTForceModel force : forceModels) {
- force.registerAttitudeProvider(attitudeProvider);
- }
- // Returns an equinoctial orbit
- return OrbitType.EQUINOCTIAL.convertType(osculating);
- }
- /** {@inheritDoc} */
- @Override
- @SuppressWarnings("unchecked")
- public <T extends CalculusFieldElement<T>> FieldOrbit<T> meanToOsculating(final FieldOrbit<T> mean) {
- final FieldAbsoluteDate<T> date = mean.getDate();
- final Field<T> field = date.getField();
- // Create the spacecraft state
- final T fieldMass = field.getZero().newInstance(mass);
- final FieldAttitude<T> attitude = attitudeProvider.getAttitude(mean, mean.getDate(), mean.getFrame());
- final FieldSpacecraftState<T> meanState = new FieldSpacecraftState<>(mean, attitude).withMass(fieldMass);
- //Create the auxiliary object
- final FieldAuxiliaryElements<T> aux = new FieldAuxiliaryElements<>(mean, +1);
- // Set the force models
- final List<FieldShortPeriodTerms<T>> shortPeriodTerms = new ArrayList<>();
- for (final DSSTForceModel force : forceModels) {
- shortPeriodTerms.addAll(force.initializeShortPeriodTerms(aux, PropagationType.OSCULATING,
- force.getParameters(field, date)));
- force.updateShortPeriodTerms(force.getParametersAllValues(field), meanState);
- }
- // recompute the osculating parameters from the current mean parameters
- return computeOsculatingOrbit(mean, shortPeriodTerms);
- }
- /** Compute osculating orbit from mean orbit.
- * <p>
- * Compute and add the short periodic variation to the mean {@link SpacecraftState}.
- * </p>
- * @param meanOrbit initial mean orbit
- * @param shortPeriodTerms short period terms
- * @param <T> type of the elements
- * @return osculating orbit
- */
- private <T extends CalculusFieldElement<T>> FieldOrbit<T> computeOsculatingOrbit(final FieldOrbit<T> meanOrbit,
- final List<FieldShortPeriodTerms<T>> shortPeriodTerms) {
- final T[] mean = MathArrays.buildArray(meanOrbit.getDate().getField(), 6);
- final T[] meanDot = MathArrays.buildArray(meanOrbit.getDate().getField(), 6);
- OrbitType.EQUINOCTIAL.mapOrbitToArray(meanOrbit, PositionAngleType.MEAN, mean, meanDot);
- final T[] y = mean.clone();
- for (final FieldShortPeriodTerms<T> spt : shortPeriodTerms) {
- final T[] shortPeriodic = spt.value(meanOrbit);
- for (int i = 0; i < shortPeriodic.length; i++) {
- y[i] = y[i].add(shortPeriodic[i]);
- }
- }
- return OrbitType.EQUINOCTIAL.mapArrayToOrbit(y, meanDot,
- PositionAngleType.MEAN,
- meanOrbit.getDate(),
- meanOrbit.getMu(),
- meanOrbit.getFrame());
- }
- }