AbstractFixedBoundaryCartesianSingleShooting.java
- /* Copyright 2022-2025 Romain Serra
- * 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.control.indirect.shooting;
- import org.hipparchus.util.FastMath;
- import org.orekit.attitudes.Attitude;
- import org.orekit.control.indirect.shooting.boundary.CartesianBoundaryConditionChecker;
- import org.orekit.control.indirect.shooting.boundary.FixedTimeBoundaryOrbits;
- import org.orekit.control.indirect.shooting.boundary.FixedTimeCartesianBoundaryStates;
- import org.orekit.control.indirect.shooting.propagation.ShootingPropagationSettings;
- import org.orekit.frames.Frame;
- import org.orekit.orbits.CartesianOrbit;
- import org.orekit.orbits.Orbit;
- import org.orekit.propagation.SpacecraftState;
- import org.orekit.propagation.numerical.NumericalPropagator;
- import org.orekit.utils.AbsolutePVCoordinates;
- import org.orekit.utils.TimeStampedPVCoordinates;
- /**
- * Abstract class for indirect single shooting methods with Cartesian coordinates for fixed time fixed boundary.
- * Terminal mass is assumed to be free, thus corresponding adjoint must vanish at terminal time.
- * On the other hand, other terminal adjoint variables are free because the Cartesian state is fixed.
- *
- * @author Romain Serra
- * @since 12.2
- * @see org.orekit.control.indirect.adjoint.CartesianAdjointDerivativesProvider
- * @see org.orekit.control.indirect.adjoint.FieldCartesianAdjointDerivativesProvider
- */
- public abstract class AbstractFixedBoundaryCartesianSingleShooting extends AbstractFixedInitialCartesianSingleShooting {
- /** Default value for defects scaling. */
- private static final double DEFAULT_SCALE = 1.;
- /** Terminal Cartesian coordinates. */
- private final TimeStampedPVCoordinates terminalCartesianState;
- /** Condition checker. */
- private final CartesianBoundaryConditionChecker conditionChecker;
- /** Scale for velocity defects (m). */
- private double scaleVelocityDefects;
- /** Scale for position defects (m/s). */
- private double scalePositionDefects;
- /** Tolerance for convergence on terminal mass adjoint, if applicable to dynamics. */
- private double toleranceMassAdjoint = DEFAULT_TOLERANCE_MASS_ADJOINT;
- /**
- * Constructor with boundary conditions as orbits.
- * @param propagationSettings propagation settings
- * @param boundaryConditions boundary conditions as {@link FixedTimeCartesianBoundaryStates}
- * @param conditionChecker boundary condition checker
- */
- protected AbstractFixedBoundaryCartesianSingleShooting(final ShootingPropagationSettings propagationSettings,
- final FixedTimeCartesianBoundaryStates boundaryConditions,
- final CartesianBoundaryConditionChecker conditionChecker) {
- super(propagationSettings, buildInitialStateTemplate(boundaryConditions.getInitialCartesianState(),
- propagationSettings));
- this.conditionChecker = conditionChecker;
- this.terminalCartesianState = boundaryConditions.getTerminalCartesianState()
- .getPVCoordinates(propagationSettings.getPropagationFrame());
- this.scalePositionDefects = DEFAULT_SCALE;
- this.scaleVelocityDefects = DEFAULT_SCALE;
- }
- /**
- * Constructor with boundary conditions as orbits.
- * @param propagationSettings propagation settings
- * @param boundaryConditions boundary conditions as {@link FixedTimeBoundaryOrbits}
- * @param conditionChecker boundary condition checker
- */
- protected AbstractFixedBoundaryCartesianSingleShooting(final ShootingPropagationSettings propagationSettings,
- final FixedTimeBoundaryOrbits boundaryConditions,
- final CartesianBoundaryConditionChecker conditionChecker) {
- super(propagationSettings, buildInitialStateTemplate(boundaryConditions.getInitialOrbit(),
- propagationSettings));
- this.conditionChecker = conditionChecker;
- this.terminalCartesianState = boundaryConditions.getTerminalOrbit().getPVCoordinates(propagationSettings.getPropagationFrame());
- this.scalePositionDefects = DEFAULT_SCALE;
- this.scaleVelocityDefects = DEFAULT_SCALE;
- }
- /**
- * Setter for scale of position defects.
- * @param scalePositionDefects new scale
- */
- public void setScalePositionDefects(final double scalePositionDefects) {
- this.scalePositionDefects = scalePositionDefects;
- }
- /**
- * Getter for scale of position defects.
- * @return scale
- */
- public double getScalePositionDefects() {
- return scalePositionDefects;
- }
- /**
- * Setter for scale of velocity defects.
- * @param scaleVelocityDefects new scale
- */
- public void setScaleVelocityDefects(final double scaleVelocityDefects) {
- this.scaleVelocityDefects = scaleVelocityDefects;
- }
- /**
- * Getter for scale of velocity defects.
- * @return scale
- */
- public double getScaleVelocityDefects() {
- return scaleVelocityDefects;
- }
- /**
- * Getter for the boundary condition checker.
- * @return checker
- */
- protected CartesianBoundaryConditionChecker getConditionChecker() {
- return conditionChecker;
- }
- /**
- * Getter for the target terminal Cartesian state vector.
- * @return expected terminal state
- */
- protected TimeStampedPVCoordinates getTerminalCartesianState() {
- return terminalCartesianState;
- }
- /**
- * Setter for mass adjoint tolerance.
- * @param toleranceMassAdjoint new tolerance value
- */
- public void setToleranceMassAdjoint(final double toleranceMassAdjoint) {
- this.toleranceMassAdjoint = FastMath.abs(toleranceMassAdjoint);
- }
- /**
- * Create template initial state (without adjoint varialbles) for propagation from orbits.
- * @param initialOrbit initial orbit
- * @param propagationSettings propagation settings
- * @return template propagation state
- */
- private static SpacecraftState buildInitialStateTemplate(final Orbit initialOrbit,
- final ShootingPropagationSettings propagationSettings) {
- final Frame frame = propagationSettings.getPropagationFrame();
- final CartesianOrbit cartesianOrbit = new CartesianOrbit(initialOrbit.getPVCoordinates(frame), frame,
- initialOrbit.getDate(), initialOrbit.getMu());
- final Attitude attitude = propagationSettings.getAttitudeProvider()
- .getAttitude(cartesianOrbit, cartesianOrbit.getDate(), cartesianOrbit.getFrame());
- return new SpacecraftState(cartesianOrbit).withAttitude(attitude);
- }
- /**
- * Create template initial state (without adjoint varialbles) for propagation.
- * @param initialCartesianState initial Cartesian state
- * @param propagationSettings propagation settings
- * @return template propagation state
- */
- private static SpacecraftState buildInitialStateTemplate(final AbsolutePVCoordinates initialCartesianState,
- final ShootingPropagationSettings propagationSettings) {
- final Frame frame = propagationSettings.getPropagationFrame();
- final AbsolutePVCoordinates absolutePVCoordinates = new AbsolutePVCoordinates(frame,
- initialCartesianState.getPVCoordinates(frame));
- final Attitude attitude = propagationSettings.getAttitudeProvider()
- .getAttitude(absolutePVCoordinates, absolutePVCoordinates.getDate(), absolutePVCoordinates.getFrame());
- return new SpacecraftState(absolutePVCoordinates, attitude);
- }
- /** {@inheritDoc} */
- @Override
- public ShootingBoundaryOutput computeCandidateSolution(final SpacecraftState initialState,
- final int iterationCount) {
- final NumericalPropagator propagator = buildPropagator(initialState);
- final SpacecraftState actualTerminalState = propagator.propagate(getTerminalCartesianState().getDate());
- final boolean converged = checkConvergence(actualTerminalState);
- return new ShootingBoundaryOutput(converged, iterationCount, initialState, getPropagationSettings(),
- actualTerminalState);
- }
- /**
- * Checks convergence.
- * @param actualTerminalState achieved terminal state
- * @return convergence flag
- */
- private boolean checkConvergence(final SpacecraftState actualTerminalState) {
- final boolean isCartesianConverged = getConditionChecker().isConverged(getTerminalCartesianState(),
- actualTerminalState.getPVCoordinates());
- if (isCartesianConverged) {
- final String adjointName = getPropagationSettings().getAdjointDynamicsProvider().getAdjointName();
- final double[] terminalAdjoint = actualTerminalState.getAdditionalState(adjointName);
- if (terminalAdjoint.length == 7) {
- return FastMath.abs(terminalAdjoint[6]) < toleranceMassAdjoint;
- } else {
- return true;
- }
- } else {
- return false;
- }
- }
- }