OrbitBlender.java
- /* Copyright 2002-2024 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.orbits;
- import org.hipparchus.analysis.polynomials.SmoothStepFactory;
- import org.orekit.errors.OrekitException;
- import org.orekit.frames.Frame;
- import org.orekit.propagation.Propagator;
- import org.orekit.propagation.SpacecraftState;
- import org.orekit.propagation.analytical.AbstractAnalyticalPropagator;
- import org.orekit.time.AbsoluteDate;
- import org.orekit.utils.PVCoordinates;
- import java.util.List;
- /**
- * Orbit blender.
- * <p>
- * Its purpose is to interpolate orbit state between tabulated orbit states using the concept of blending, exposed in :
- * "Efficient Covariance Interpolation using Blending of Approximate State Error Transitions" by Sergei Tanygin, and applying
- * it to orbit states instead of covariances.
- * <p>
- * It propagates tabulated values to the interpolating time using given propagator and then blend each propagated
- * states using a smoothstep function. It gives especially good results as explained
- * <a href="https://orekit.org/doc/technical-notes/Implementation_of_covariance_interpolation_in_Orekit.pdf">here</a>
- * compared to Hermite interpolation when time steps between tabulated values get significant (In LEO, > 10 mn for
- * example).
- * <p>
- * <b>In most cases, an analytical propagator would be used to quickly fill the gap between tabulated values and recreate
- * a dense ephemeris</b>.
- * <p>
- * However, a fully configured and accurate numerical propagator can be used to recreate an even
- * more precise ephemeris in case the initial tabulated values were obtained from an external source.
- * <p>
- * Note that in the current implementation, the returned blended orbit is necessarily Cartesian.
- *
- * @author Vincent Cucchietti
- * @see org.hipparchus.analysis.polynomials.SmoothStepFactory
- * @see org.hipparchus.analysis.polynomials.SmoothStepFactory.SmoothStepFunction
- * @see Propagator
- * @see AbstractAnalyticalPropagator
- *
- * @since 12.0
- */
- public class OrbitBlender extends AbstractOrbitInterpolator {
- /** Propagator used to propagate tabulated orbits to interpolating time. */
- private final Propagator blendingPropagator;
- /** Blending function. */
- private final SmoothStepFactory.SmoothStepFunction blendingFunction;
- /**
- * Default constructor.
- * <p>
- * <b>In most cases, an analytical propagator would be used to quickly fill the gap between tabulated values and recreate
- * a dense ephemeris</b>.
- * <p>
- * However, a fully configured and accurate numerical propagator can be used to recreate an even
- * more precise ephemeris in case the initial tabulated values were obtained from an external source.
- *
- * @param blendingFunction
- * {@link org.hipparchus.analysis.polynomials.SmoothStepFactory.SmoothStepFunction smoothstep function} used for
- * blending
- * @param blendingPropagator propagator used to propagate tabulated orbits to interpolating time
- * @param outputInertialFrame output inertial frame
- *
- * @throws OrekitException if output frame is not inertial
- * @see org.hipparchus.analysis.polynomials.SmoothStepFactory.SmoothStepFunction
- */
- public OrbitBlender(final SmoothStepFactory.SmoothStepFunction blendingFunction,
- final Propagator blendingPropagator,
- final Frame outputInertialFrame) {
- super(DEFAULT_INTERPOLATION_POINTS, 0., outputInertialFrame);
- this.blendingFunction = blendingFunction;
- this.blendingPropagator = blendingPropagator;
- }
- /** {@inheritDoc} */
- @Override
- protected Orbit interpolate(final InterpolationData interpolationData) {
- // Get first and last entry
- final List<Orbit> neighborList = interpolationData.getNeighborList();
- final Orbit previousOrbit = neighborList.get(0);
- final Orbit nextOrbit = neighborList.get(1);
- // Propagate orbits
- final AbsoluteDate interpolationDate = interpolationData.getInterpolationDate();
- final Orbit forwardedOrbit = propagateOrbit(previousOrbit, interpolationDate);
- final Orbit backwardedOrbit = propagateOrbit(nextOrbit, interpolationDate);
- // Extract position-velocity-acceleration coordinates
- final PVCoordinates forwardedPV = forwardedOrbit.getPVCoordinates(getOutputInertialFrame());
- final PVCoordinates backwardedPV = backwardedOrbit.getPVCoordinates(getOutputInertialFrame());
- // Blend PV coordinates
- final double timeParameter = getTimeParameter(interpolationDate, previousOrbit.getDate(), nextOrbit.getDate());
- final double blendingValue = blendingFunction.value(timeParameter);
- final PVCoordinates blendedPV = forwardedPV.blendArithmeticallyWith(backwardedPV, blendingValue);
- // Output new blended instance
- return new CartesianOrbit(blendedPV, getOutputInertialFrame(), interpolationDate, previousOrbit.getMu());
- }
- /**
- * Propagate orbit using predefined {@link Propagator propagator}.
- *
- * @param tabulatedOrbit tabulated orbit to propagate
- * @param propagationDate propagation date
- *
- * @return orbit propagated to propagation date
- */
- private Orbit propagateOrbit(final Orbit tabulatedOrbit,
- final AbsoluteDate propagationDate) {
- blendingPropagator.resetInitialState(new SpacecraftState(tabulatedOrbit));
- return blendingPropagator.propagate(propagationDate).getOrbit();
- }
- }