Commit 8be4fba3 authored by Bryan Cazabonne's avatar Bryan Cazabonne
Browse files

Merge branch 'develop' into kalman-dsst

parents 6364a7e3 6a590caf
Pipeline #1674 passed with stages
in 22 minutes and 17 seconds
......@@ -21,6 +21,30 @@
</properties>
<body>
<release version="11.1" date="TBD" description="TBD">
<action dev="bryan" type="add">
Added a new and simpler API for State Transition Matrix and Jacobian
matrix computation for analytical orbit propagators.
</action>
<action dev="bryan" type="fix" issue="878">
Fixed writing of ITRF frames before 2000 when generating CCSDS files.
</action>
<action dev="luc" type="fix" issue="836">
Use the orbit normalization feature to reduce discontinuities across impulsive maneuvers.
</action>
<action dev="luc" type="add">
Added an orbit normalization feature.
</action>
<action dev="evan" type="add" issue="881">
Add AbsoluteDate.toStringWithoutUtcOffset(TimeScale, int) and
DateTimeComponents.toStringWithoutUtcOffset(int, int) to emulate
AbsoluteDate.toString() from Orekit 10.
</action>
<action dev="evan" type="fix" issue="880">
Fix UTC offset in DateTimeComponents.toString(int, int)
</action>
<action dev="luc" type="fix" issue="849">
Added detector to FieldEventHandler.init arguments list.
</action>
<action dev="luc" type="fix" issue="837">
Added getters for raw detectors in event shifter, slope filter and predicate filter.
</action>
......
......@@ -56,7 +56,7 @@ public class BatchLSModel extends AbstractBatchLSModel {
/** {@inheritDoc} */
@Override
protected MatricesHarvester configureHarvester(final Propagator propagator) {
return ((NumericalPropagator) propagator).setupMatricesComputation(STM_NAME, null, null);
return propagator.setupMatricesComputation(STM_NAME, null, null);
}
/** {@inheritDoc} */
......
......@@ -76,7 +76,7 @@ public class DSSTBatchLSModel extends AbstractBatchLSModel {
/** {@inheritDoc} */
@Override
protected MatricesHarvester configureHarvester(final Propagator propagator) {
return ((DSSTPropagator) propagator).setupMatricesComputation(STM_NAME, null, null);
return propagator.setupMatricesComputation(STM_NAME, null, null);
}
/** {@inheritDoc} */
......
......@@ -24,7 +24,6 @@ import org.orekit.propagation.MatricesHarvester;
import org.orekit.propagation.Propagator;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.analytical.tle.TLEJacobiansMapper;
import org.orekit.propagation.analytical.tle.TLEPartialDerivativesEquations;
import org.orekit.propagation.analytical.tle.TLEPropagator;
import org.orekit.propagation.conversion.OrbitDeterminationPropagatorBuilder;
import org.orekit.utils.ParameterDriversList;
......@@ -32,16 +31,13 @@ import org.orekit.utils.ParameterDriversList;
/** Bridge between {@link ObservedMeasurement measurements} and {@link
* org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem
* least squares problems}.
* <p>
* This class is an adaption of the {@link BatchLSModel} class
* but for the {@link TLEPropagator TLE propagator}.
* </p>
* @author Luc Maisonobe
* @author Bryan Cazabonne
* @author Thomas Paulet
* @since 11.0
*
* @deprecated as of 11.1, replaced by {@link BatchLSModel}
*/
@Deprecated
public class TLEBatchLSModel extends AbstractBatchLSModel {
/** Name of the State Transition Matrix state. */
......@@ -61,13 +57,19 @@ public class TLEBatchLSModel extends AbstractBatchLSModel {
super(propagatorBuilders, measurements, estimatedMeasurementsParameters, observer);
}
/** {@inheritDoc} */
@Override
protected MatricesHarvester configureHarvester(final Propagator propagator) {
return ((TLEPropagator) propagator).setupMatricesComputation(STM_NAME, null, null);
}
/** {@inheritDoc} */
@Override
@Deprecated
protected TLEJacobiansMapper configureDerivatives(final Propagator propagator) {
final TLEPartialDerivativesEquations partials =
new TLEPartialDerivativesEquations(STM_NAME, (TLEPropagator) propagator);
final org.orekit.propagation.analytical.tle.TLEPartialDerivativesEquations partials =
new org.orekit.propagation.analytical.tle.TLEPartialDerivativesEquations(STM_NAME, (TLEPropagator) propagator);
// add the derivatives to the initial state
final SpacecraftState rawState = propagator.getInitialState();
......
......@@ -23,7 +23,6 @@ import org.orekit.propagation.PropagationType;
import org.orekit.propagation.Propagator;
import org.orekit.propagation.conversion.OrbitDeterminationPropagatorBuilder;
import org.orekit.propagation.numerical.JacobiansMapper;
import org.orekit.propagation.numerical.NumericalPropagator;
import org.orekit.utils.ParameterDriversList;
/** Class defining the process model dynamics to use with a {@link KalmanEstimator}.
......@@ -63,7 +62,7 @@ public class KalmanModel extends AbstractKalmanModel {
for (int k = 0; k < propagators.length; ++k) {
// Link the partial derivatives to this new propagator
final String equationName = KalmanEstimator.class.getName() + "-derivatives-" + k;
harvesters[k] = ((NumericalPropagator) getReferenceTrajectories()[k]).setupMatricesComputation(equationName, null, null);
harvesters[k] = getReferenceTrajectories()[k].setupMatricesComputation(equationName, null, null);
}
// Update Jacobian harvesters
......
......@@ -22,9 +22,7 @@ import org.orekit.annotation.DefaultDataContext;
import org.orekit.propagation.MatricesHarvester;
import org.orekit.propagation.PropagationType;
import org.orekit.propagation.Propagator;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.analytical.tle.TLEJacobiansMapper;
import org.orekit.propagation.analytical.tle.TLEPartialDerivativesEquations;
import org.orekit.propagation.analytical.tle.TLEPropagator;
import org.orekit.propagation.conversion.OrbitDeterminationPropagatorBuilder;
import org.orekit.utils.ParameterDriversList;
......@@ -39,7 +37,9 @@ import org.orekit.utils.ParameterDriversList;
* @author Bryan Cazabonne
* @author Thomas Paulet
* @since 11.0
* @deprecated as of 11.1, replaced by {@link KalmanModel}
*/
@Deprecated
public class TLEKalmanModel extends AbstractKalmanModel {
/** Kalman process model constructor (package private).
......@@ -73,13 +73,7 @@ public class TLEKalmanModel extends AbstractKalmanModel {
for (int k = 0; k < propagators.length; ++k) {
// Link the partial derivatives to this new propagator
final String equationName = KalmanEstimator.class.getName() + "-derivatives-" + k;
final TLEPartialDerivativesEquations pde = new TLEPartialDerivativesEquations(equationName, (TLEPropagator) getReferenceTrajectories()[k]);
// Reset the Jacobians
final SpacecraftState rawState = getReferenceTrajectories()[k].getInitialState();
final SpacecraftState stateWithDerivatives = pde.setInitialJacobians(rawState);
((TLEPropagator) getReferenceTrajectories()[k]).resetInitialState(stateWithDerivatives);
harvesters[k] = pde.getMapper();
harvesters[k] = ((TLEPropagator) getReferenceTrajectories()[k]).setupMatricesComputation(equationName, null, null);
}
// Update Jacobian harvesters
......
......@@ -187,6 +187,12 @@ public enum CelestialBodyFrame {
/** International Terrestrial Reference Frame 1997. */
ITRF1997 {
/** {@inheritDoc} */
@Override
public String getName() {
return "ITRF-97";
}
/** {@inheritDoc} */
@Override
public Frame getFrame(final IERSConventions conventions,
......@@ -203,6 +209,12 @@ public enum CelestialBodyFrame {
/** International Terrestrial Reference Frame 1996. */
ITRF1996 {
/** {@inheritDoc} */
@Override
public String getName() {
return "ITRF-96";
}
/** {@inheritDoc} */
@Override
public Frame getFrame(final IERSConventions conventions,
......@@ -219,6 +231,12 @@ public enum CelestialBodyFrame {
/** International Terrestrial Reference Frame 1994. */
ITRF1994 {
/** {@inheritDoc} */
@Override
public String getName() {
return "ITRF-94";
}
/** {@inheritDoc} */
@Override
public Frame getFrame(final IERSConventions conventions,
......@@ -235,6 +253,12 @@ public enum CelestialBodyFrame {
/** International Terrestrial Reference Frame 1993. */
ITRF1993 {
/** {@inheritDoc} */
@Override
public String getName() {
return "ITRF-93";
}
/** {@inheritDoc} */
@Override
public Frame getFrame(final IERSConventions conventions,
......@@ -251,6 +275,12 @@ public enum CelestialBodyFrame {
/** International Terrestrial Reference Frame 1992. */
ITRF1992 {
/** {@inheritDoc} */
@Override
public String getName() {
return "ITRF-92";
}
/** {@inheritDoc} */
@Override
public Frame getFrame(final IERSConventions conventions,
......@@ -267,6 +297,12 @@ public enum CelestialBodyFrame {
/** International Terrestrial Reference Frame 1991. */
ITRF1991 {
/** {@inheritDoc} */
@Override
public String getName() {
return "ITRF-91";
}
/** {@inheritDoc} */
@Override
public Frame getFrame(final IERSConventions conventions,
......@@ -283,6 +319,12 @@ public enum CelestialBodyFrame {
/** International Terrestrial Reference Frame 1990. */
ITRF1990 {
/** {@inheritDoc} */
@Override
public String getName() {
return "ITRF-90";
}
/** {@inheritDoc} */
@Override
public Frame getFrame(final IERSConventions conventions,
......@@ -299,6 +341,12 @@ public enum CelestialBodyFrame {
/** International Terrestrial Reference Frame 1989. */
ITRF1989 {
/** {@inheritDoc} */
@Override
public String getName() {
return "ITRF-89";
}
/** {@inheritDoc} */
@Override
public Frame getFrame(final IERSConventions conventions,
......@@ -315,6 +363,12 @@ public enum CelestialBodyFrame {
/** International Terrestrial Reference Frame 1988. */
ITRF1988 {
/** {@inheritDoc} */
@Override
public String getName() {
return "ITRF-88";
}
/** {@inheritDoc} */
@Override
public Frame getFrame(final IERSConventions conventions,
......@@ -409,6 +463,15 @@ public enum CelestialBodyFrame {
*/
public abstract Frame getFrame(IERSConventions conventions, boolean simpleEOP, DataContext dataContext);
/**
* Get the name of celestial body frame.
* @return the name of celestial body frame
* @since 11.1
*/
public String getName() {
return name();
}
/** Parse a CCSDS frame.
* @param frameName name of the frame, as the value of a CCSDS key=value line
* @return CCSDS frame corresponding to the name
......
......@@ -114,7 +114,7 @@ public class FrameFacade {
*/
public static FrameFacade map(final Frame frame) {
final CelestialBodyFrame cbf = CelestialBodyFrame.map(frame);
return new FrameFacade(frame, cbf, null, null, cbf.name());
return new FrameFacade(frame, cbf, null, null, cbf.getName());
}
/** Simple constructor.
......@@ -138,7 +138,7 @@ public class FrameFacade {
final CelestialBodyFrame cbf = CelestialBodyFrame.parse(name);
if (allowCelestial) {
return new FrameFacade(cbf.getFrame(conventions, simpleEOP, dataContext),
cbf, null, null, cbf.name());
cbf, null, null, cbf.getName());
}
} catch (IllegalArgumentException iaeC) {
try {
......
......@@ -234,7 +234,7 @@ public class ImpulseManeuver<T extends EventDetector> extends AbstractDetector<I
final double newMass = oldState.getMass() * FastMath.exp(-sign * deltaV.getNorm() / im.vExhaust);
// pack everything in a new state
SpacecraftState newState = new SpacecraftState(oldState.getOrbit().getType().convertType(newOrbit),
SpacecraftState newState = new SpacecraftState(oldState.getOrbit().getType().normalize(newOrbit, oldState.getOrbit()),
attitude, newMass);
for (final DoubleArrayDictionary.Entry entry : oldState.getAdditionalStatesValues().getData()) {
newState = newState.addAdditionalState(entry.getKey(), entry.getValue());
......
......@@ -222,7 +222,9 @@ public abstract class IntervalEventTrigger<T extends AbstractDetector<T>> extend
/** {@inheritDoc} */
@Override
public void init(final FieldSpacecraftState<S> initialState, final FieldAbsoluteDate<S> target) {
public void init(final FieldSpacecraftState<S> initialState,
final FieldAbsoluteDate<S> target,
final D detector) {
forward = target.isAfterOrEqualTo(initialState);
initializeResetters(initialState, target);
}
......
......@@ -370,7 +370,9 @@ public abstract class StartStopEventsTrigger<A extends AbstractDetector<A>, O ex
/** {@inheritDoc} */
@Override
public void init(final FieldSpacecraftState<S> initialState, final FieldAbsoluteDate<S> target) {
public void init(final FieldSpacecraftState<S> initialState,
final FieldAbsoluteDate<S> target,
final D detector) {
forward = target.isAfterOrEqualTo(initialState);
initializeResetters(initialState, target);
}
......@@ -411,7 +413,9 @@ public abstract class StartStopEventsTrigger<A extends AbstractDetector<A>, O ex
/** {@inheritDoc} */
@Override
public void init(final FieldSpacecraftState<S> initialState, final FieldAbsoluteDate<S> target) {
public void init(final FieldSpacecraftState<S> initialState,
final FieldAbsoluteDate<S> target,
final D detector) {
forward = target.isAfterOrEqualTo(initialState);
initializeResetters(initialState, target);
}
......
......@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.Queue;
import org.hipparchus.linear.RealMatrix;
import org.orekit.attitudes.AttitudeProvider;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
......@@ -62,12 +63,16 @@ public abstract class AbstractPropagator implements Propagator {
/** Initial state. */
private SpacecraftState initialState;
/** Harvester for State Transition Matrix and Jacobian matrix. */
private AbstractMatricesHarvester harvester;
/** Build a new instance.
*/
protected AbstractPropagator() {
multiplexer = new StepHandlerMultiplexer();
multiplexer = new StepHandlerMultiplexer();
additionalStateProviders = new ArrayList<>();
unmanagedStates = new HashMap<>();
unmanagedStates = new HashMap<>();
harvester = null;
}
/** Set a start date.
......@@ -137,6 +142,41 @@ public abstract class AbstractPropagator implements Propagator {
return Collections.unmodifiableList(additionalStateProviders);
}
/** {@inheritDoc} */
@Override
public MatricesHarvester setupMatricesComputation(final String stmName, final RealMatrix initialStm,
final DoubleArrayDictionary initialJacobianColumns) {
if (stmName == null) {
throw new OrekitException(OrekitMessages.NULL_ARGUMENT, "stmName");
}
harvester = createHarvester(stmName, initialStm, initialJacobianColumns);
return harvester;
}
/** Create the harvester suitable for propagator.
* @param stmName State Transition Matrix state name
* @param initialStm initial State Transition Matrix ∂Y/∂Y₀,
* if null (which is the most frequent case), assumed to be 6x6 identity
* @param initialJacobianColumns initial columns of the Jacobians matrix with respect to parameters,
* if null or if some selected parameters are missing from the dictionary, the corresponding
* initial column is assumed to be 0
* @return harvester to retrieve computed matrices during and after propagation
* @since 11.1
*/
protected AbstractMatricesHarvester createHarvester(final String stmName, final RealMatrix initialStm,
final DoubleArrayDictionary initialJacobianColumns) {
// FIXME: not implemented as of 11.1
throw new UnsupportedOperationException();
}
/** Get the harvester.
* @return harvester, or null if it was not created
* @since 11.1
*/
protected AbstractMatricesHarvester getHarvester() {
return harvester;
}
/** Update state by adding unmanaged states.
* @param original original state
* @return updated state, with unmanaged states included
......
/* Copyright 2002-2022 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.analytical;
import java.util.ArrayList;
import java.util.List;
import org.hipparchus.analysis.differentiation.Gradient;
import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.orekit.attitudes.AttitudeProvider;
import org.orekit.attitudes.FieldAttitude;
import org.orekit.orbits.FieldCartesianOrbit;
import org.orekit.orbits.FieldOrbit;
import org.orekit.propagation.FieldSpacecraftState;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.integration.AbstractGradientConverter;
import org.orekit.utils.FieldAngularCoordinates;
import org.orekit.utils.FieldPVCoordinates;
import org.orekit.utils.ParameterDriver;
import org.orekit.utils.TimeStampedFieldAngularCoordinates;
import org.orekit.utils.TimeStampedFieldPVCoordinates;
/**
* Converter for analytical orbit propagator.
*
* @author Bryan Cazabonne
* @since 11.1
*/
public abstract class AbstractAnalyticalGradientConverter extends AbstractGradientConverter {
/** Attitude provider. */
private final AttitudeProvider provider;
/** States with various number of additional propagation parameters. */
private final List<FieldSpacecraftState<Gradient>> gStates;
/**
* Constructor.
* @param propagator analytical orbit propagator
* @param mu central attraction coefficient
* @param freeStateParameters number of free parameters
*/
protected AbstractAnalyticalGradientConverter(final AbstractAnalyticalPropagator propagator,
final double mu,
final int freeStateParameters) {
super(freeStateParameters);
// Attitude provider
this.provider = propagator.getAttitudeProvider();
// Spacecraft state
final SpacecraftState state = propagator.getInitialState();
// Position always has derivatives
final Vector3D pos = state.getPVCoordinates().getPosition();
final FieldVector3D<Gradient> posG = new FieldVector3D<>(Gradient.variable(freeStateParameters, 0, pos.getX()),
Gradient.variable(freeStateParameters, 1, pos.getY()),
Gradient.variable(freeStateParameters, 2, pos.getZ()));
// Velocity may have derivatives or not
final Vector3D vel = state.getPVCoordinates().getVelocity();
final FieldVector3D<Gradient> velG = new FieldVector3D<>(Gradient.variable(freeStateParameters, 3, vel.getX()),
Gradient.variable(freeStateParameters, 4, vel.getY()),
Gradient.variable(freeStateParameters, 5, vel.getZ()));
// Acceleration never has derivatives
final Vector3D acc = state.getPVCoordinates().getAcceleration();
final FieldVector3D<Gradient> accG = new FieldVector3D<>(Gradient.constant(freeStateParameters, acc.getX()),
Gradient.constant(freeStateParameters, acc.getY()),
Gradient.constant(freeStateParameters, acc.getZ()));
// Mass never has derivatives
final Gradient gM = Gradient.constant(freeStateParameters, state.getMass());
final Gradient gMu = Gradient.constant(freeStateParameters, mu);
final FieldOrbit<Gradient> gOrbit =
new FieldCartesianOrbit<>(new TimeStampedFieldPVCoordinates<>(state.getDate(), posG, velG, accG),
state.getFrame(), gMu);
// Attitude
final FieldAttitude<Gradient> gAttitude = provider.getAttitude(gOrbit, gOrbit.getDate(), gOrbit.getFrame());
// Initialize the list with the state having 0 force model parameters
gStates = new ArrayList<>();
gStates.add(new FieldSpacecraftState<>(gOrbit, gAttitude, gM));
}
/** Get the state with the number of parameters consistent with the propagation model.
* @return state with the number of parameters consistent with the propagation model
*/
public FieldSpacecraftState<Gradient> getState() {
// Count the required number of parameters
int nbParams = 0;
for (final ParameterDriver driver : getParametersDrivers()) {
if (driver.isSelected()) {
++nbParams;
}
}
// Fill in intermediate slots
while (gStates.size() < nbParams + 1) {
gStates.add(null);
}
if (gStates.get(nbParams) == null) {
// It is the first time we need this number of parameters
// We need to create the state
final int freeParameters = getFreeStateParameters() + nbParams;
final FieldSpacecraftState<Gradient> s0 = gStates.get(0);
// Orbit
final FieldPVCoordinates<Gradient> pv0 = s0.getPVCoordinates();
final FieldOrbit<Gradient> gOrbit =
new FieldCartesianOrbit<>(new TimeStampedFieldPVCoordinates<>(s0.getDate().toAbsoluteDate(),
extend(pv0.getPosition(), freeParameters),
extend(pv0.getVelocity(), freeParameters),
extend(pv0.getAcceleration(), freeParameters)),
s0.getFrame(),
extend(s0.getMu(), freeParameters));
// Attitude
final FieldAngularCoordinates<Gradient> ac0 = s0.getAttitude().getOrientation();
final FieldAttitude<Gradient> gAttitude =
new FieldAttitude<>(s0.getAttitude().getReferenceFrame(),
new TimeStampedFieldAngularCoordinates<>(gOrbit.getDate(),
extend(ac0.getRotation(), freeParameters),
extend(ac0.getRotationRate(), freeParameters),
extend(ac0.getRotationAcceleration(), freeParameters)));
// Mass
final Gradient gM = extend(s0.getMass(), freeParameters);
gStates.set(nbParams, new FieldSpacecraftState<>(gOrbit, gAttitude, gM));
}
return gStates.get(nbParams);
}
/** Get the model parameters.
* @param state state as returned by {@link #getState()}
* @return the model parameters
*/
public Gradient[] getParameters(final FieldSpacecraftState<Gradient> state) {
final int freeParameters = state.getMass().getFreeParameters();