NewtonFixedBoundaryCartesianSingleShooting.java

  1. /* Copyright 2022-2024 Romain Serra
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.control.indirect.shooting;

  18. import org.hipparchus.analysis.differentiation.Gradient;
  19. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  20. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  21. import org.hipparchus.linear.DecompositionSolver;
  22. import org.hipparchus.linear.LUDecomposition;
  23. import org.hipparchus.linear.MatrixUtils;
  24. import org.hipparchus.linear.RealMatrix;
  25. import org.hipparchus.linear.RealVector;
  26. import org.orekit.control.indirect.shooting.boundary.CartesianBoundaryConditionChecker;
  27. import org.orekit.control.indirect.shooting.boundary.FixedTimeBoundaryOrbits;
  28. import org.orekit.control.indirect.shooting.boundary.FixedTimeCartesianBoundaryStates;
  29. import org.orekit.control.indirect.shooting.propagation.ShootingPropagationSettings;
  30. import org.orekit.propagation.FieldSpacecraftState;
  31. import org.orekit.utils.FieldPVCoordinates;

  32. /**
  33.  * Class for indirect single shooting methods with Cartesian coordinates for fixed time fixed boundary.
  34.  * Update is the classical Newton-Raphson one.
  35.  *
  36.  * @author Romain Serra
  37.  * @since 12.2
  38.  */
  39. public class NewtonFixedBoundaryCartesianSingleShooting extends AbstractFixedBoundaryCartesianSingleShooting {

  40.     /**
  41.      * Constructor with boundary conditions as orbits.
  42.      * @param propagationSettings propagation settings
  43.      * @param boundaryConditions boundary conditions as {@link FixedTimeCartesianBoundaryStates}
  44.      * @param convergenceChecker convergence checker
  45.      */
  46.     public NewtonFixedBoundaryCartesianSingleShooting(final ShootingPropagationSettings propagationSettings,
  47.                                                       final FixedTimeCartesianBoundaryStates boundaryConditions,
  48.                                                       final CartesianBoundaryConditionChecker convergenceChecker) {
  49.         super(propagationSettings, boundaryConditions, convergenceChecker);
  50.     }

  51.     /**
  52.      * Constructor with boundary conditions as orbits.
  53.      * @param propagationSettings propagation settings
  54.      * @param boundaryConditions boundary conditions as {@link FixedTimeBoundaryOrbits}
  55.      * @param convergenceChecker convergence checker
  56.      */
  57.     public NewtonFixedBoundaryCartesianSingleShooting(final ShootingPropagationSettings propagationSettings,
  58.                                                       final FixedTimeBoundaryOrbits boundaryConditions,
  59.                                                       final CartesianBoundaryConditionChecker convergenceChecker) {
  60.         super(propagationSettings, boundaryConditions, convergenceChecker);
  61.     }

  62.     /** {@inheritDoc} */
  63.     @Override
  64.     protected double[] updateAdjoint(final double[] originalInitialAdjoint,
  65.                                      final FieldSpacecraftState<Gradient> fieldTerminalState) {
  66.         // form defects and their Jacobian matrix
  67.         final double[] defects = new double[originalInitialAdjoint.length];
  68.         final double[][] defectsJacobianData = new double[defects.length][defects.length];
  69.         final double reciprocalScalePosition = 1. / getScalePositionDefects();
  70.         final double reciprocalScaleVelocity = 1. / getScaleVelocityDefects();
  71.         final FieldPVCoordinates<Gradient> terminalPV = fieldTerminalState.getPVCoordinates();
  72.         final FieldVector3D<Gradient> fieldScaledTerminalPosition = terminalPV.getPosition().scalarMultiply(reciprocalScalePosition);
  73.         final FieldVector3D<Gradient> fieldScaledTerminalVelocity = terminalPV.getVelocity().scalarMultiply(reciprocalScaleVelocity);
  74.         final Vector3D terminalScaledPosition = fieldScaledTerminalPosition.toVector3D();
  75.         final Vector3D terminalScaledVelocity = fieldScaledTerminalVelocity.toVector3D();
  76.         final Vector3D targetScaledPosition = getTerminalCartesianState().getPosition().scalarMultiply(reciprocalScalePosition);
  77.         final Vector3D targetScaledVelocity = getTerminalCartesianState().getVelocity().scalarMultiply(reciprocalScaleVelocity);
  78.         defects[0] = terminalScaledPosition.getX() - targetScaledPosition.getX();
  79.         defectsJacobianData[0] = fieldScaledTerminalPosition.getX().getGradient();
  80.         defects[1] = terminalScaledPosition.getY() - targetScaledPosition.getY();
  81.         defectsJacobianData[1] = fieldScaledTerminalPosition.getY().getGradient();
  82.         defects[2] = terminalScaledPosition.getZ() - targetScaledPosition.getZ();
  83.         defectsJacobianData[2] = fieldScaledTerminalPosition.getZ().getGradient();
  84.         defects[3] = terminalScaledVelocity.getX() - targetScaledVelocity.getX();
  85.         defectsJacobianData[3] = fieldScaledTerminalVelocity.getX().getGradient();
  86.         defects[4] = terminalScaledVelocity.getY() - targetScaledVelocity.getY();
  87.         defectsJacobianData[4] = fieldScaledTerminalVelocity.getY().getGradient();
  88.         defects[5] = terminalScaledVelocity.getZ() - targetScaledVelocity.getZ();
  89.         defectsJacobianData[5] = fieldScaledTerminalVelocity.getZ().getGradient();
  90.         if (originalInitialAdjoint.length != 6) {
  91.             final String adjointName = getPropagationSettings().getAdjointDynamicsProvider().getAdjointName();
  92.             final Gradient terminalMassAdjoint = fieldTerminalState.getAdditionalState(adjointName)[6];
  93.             defects[6] = terminalMassAdjoint.getValue();
  94.             defectsJacobianData[6] = terminalMassAdjoint.getGradient();
  95.         }
  96.         // apply Newton's formula
  97.         final double[] correction = computeCorrection(defects, defectsJacobianData);
  98.         final double[] correctedAdjoint = originalInitialAdjoint.clone();
  99.         for (int i = 0; i < correction.length; i++) {
  100.             correctedAdjoint[i] += correction[i];
  101.         }
  102.         return correctedAdjoint;
  103.     }

  104.     /**
  105.      * Compute Newton-Raphson correction.
  106.      * @param defects defects
  107.      * @param defectsJacobianData Jacobian matrix of defects w.r.t. shooting variables
  108.      * @return correction to shooting variables
  109.      */
  110.     private double[] computeCorrection(final double[] defects, final double[][] defectsJacobianData) {
  111.         final RealMatrix defectsJacobian = MatrixUtils.createRealMatrix(defectsJacobianData);
  112.         final DecompositionSolver solver = new LUDecomposition(defectsJacobian).getSolver();
  113.         final RealVector negatedDefects = MatrixUtils.createRealVector(defects).mapMultiply(-1);
  114.         return solver.solve(negatedDefects).toArray();
  115.     }
  116. }