CartesianFuelCost.java

  1. /* Copyright 2022-2025 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.adjoint.cost;


  18. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  19. import org.orekit.propagation.SpacecraftState;
  20. import org.orekit.propagation.events.EventDetectionSettings;
  21. import org.orekit.propagation.events.EventDetector;

  22. import java.util.stream.Stream;

  23. /**
  24.  * Class for fuel cost with Cartesian coordinates.
  25.  * It is the integral over time of the Euclidean norm of the thrust vector.
  26.  *
  27.  * @author Romain Serra
  28.  * @see CartesianCost
  29.  * @since 13.0
  30.  */
  31. public class CartesianFuelCost extends AbstractCartesianCost {

  32.     /** Maximum value of thrust force Euclidean norm. */
  33.     private final double maximumThrustMagnitude;

  34.     /** Detection settings for singularity detection. */
  35.     private final EventDetectionSettings eventDetectionSettings;

  36.     /**
  37.      * Constructor with default detection settings.
  38.      * @param name name
  39.      * @param massFlowRateFactor mass flow rate factor
  40.      * @param maximumThrustMagnitude maximum thrust magnitude
  41.      */
  42.     public CartesianFuelCost(final String name, final double massFlowRateFactor, final double maximumThrustMagnitude) {
  43.         this(name, massFlowRateFactor, maximumThrustMagnitude, EventDetectionSettings.getDefaultEventDetectionSettings());
  44.     }

  45.     /**
  46.      * Constructor.
  47.      * @param name name
  48.      * @param massFlowRateFactor mass flow rate factor
  49.      * @param maximumThrustMagnitude maximum thrust magnitude
  50.      * @param eventDetectionSettings singularity event detection settings
  51.      */
  52.     public CartesianFuelCost(final String name, final double massFlowRateFactor, final double maximumThrustMagnitude,
  53.                              final EventDetectionSettings eventDetectionSettings) {
  54.         super(name, massFlowRateFactor);
  55.         this.maximumThrustMagnitude = maximumThrustMagnitude;
  56.         this.eventDetectionSettings = eventDetectionSettings;
  57.     }

  58.     /** Getter for maximum thrust magnitude.
  59.      * @return maximum thrust
  60.      */
  61.     public double getMaximumThrustMagnitude() {
  62.         return maximumThrustMagnitude;
  63.     }

  64.     /**
  65.      * Getter for event detection settings.
  66.      * @return detection settings.
  67.      */
  68.     public EventDetectionSettings getEventDetectionSettings() {
  69.         return eventDetectionSettings;
  70.     }

  71.     /**
  72.      * Evaluate switching function (whose sign determines the bang-bang control profile).
  73.      * @param adjointVariables adjoint vector
  74.      * @param mass mass
  75.      * @return value of switch function
  76.      */
  77.     private double evaluateSwitchFunction(final double[] adjointVariables, final double mass) {
  78.         double switchFunction = getAdjointVelocityNorm(adjointVariables) / mass - 1.;
  79.         if (getAdjointDimension() > 6) {
  80.             switchFunction -= adjointVariables[6] * getMassFlowRateFactor();
  81.         }
  82.         return switchFunction;
  83.     }

  84.     /**
  85.      * Computes the direction of thrust.
  86.      * @param adjointVariables adjoint vector
  87.      * @return thrust direction
  88.      */
  89.     private Vector3D getThrustDirection(final double[] adjointVariables) {
  90.         return new Vector3D(adjointVariables[3], adjointVariables[4], adjointVariables[5]).normalize();
  91.     }

  92.     /** {@inheritDoc} */
  93.     @Override
  94.     public Vector3D getThrustAccelerationVector(final double[] adjointVariables, final double mass) {
  95.         final double switchFunction = evaluateSwitchFunction(adjointVariables, mass);
  96.         if (switchFunction > 0.) {
  97.             return getThrustDirection(adjointVariables).scalarMultiply(maximumThrustMagnitude / mass);
  98.         } else {
  99.             return Vector3D.ZERO;
  100.         }
  101.     }

  102.     /** {@inheritDoc} */
  103.     @Override
  104.     public void updateAdjointDerivatives(final double[] adjointVariables, final double mass,
  105.                                          final double[] adjointDerivatives) {
  106.         if (getAdjointDimension() > 6) {
  107.             final double switchFunction = evaluateSwitchFunction(adjointVariables, mass);
  108.             if (switchFunction > 0.) {
  109.                 adjointDerivatives[6] += getAdjointVelocityNorm(adjointVariables) * maximumThrustMagnitude / (mass * mass);
  110.             }
  111.         }
  112.     }

  113.     /** {@inheritDoc} */
  114.     @Override
  115.     public double getHamiltonianContribution(final double[] adjointVariables, final double mass) {
  116.         final Vector3D thrustForce = getThrustAccelerationVector(adjointVariables, mass).scalarMultiply(mass);
  117.         return -thrustForce.getNorm();
  118.     }

  119.     /** {@inheritDoc} */
  120.     @Override
  121.     public Stream<EventDetector> getEventDetectors() {
  122.         return Stream.of(new FuelCostSwitchDetector(eventDetectionSettings));
  123.     }

  124.     /**
  125.      * Event detector for bang-bang switches.
  126.      */
  127.     private class FuelCostSwitchDetector extends ControlSwitchDetector {

  128.         /**
  129.          * Constructor.
  130.          * @param detectionSettings detection settings.
  131.          */
  132.         FuelCostSwitchDetector(final EventDetectionSettings detectionSettings) {
  133.             super(detectionSettings);
  134.         }

  135.         /** {@inheritDoc} */
  136.         @Override
  137.         public double g(final SpacecraftState state) {
  138.             final double[] adjoint = state.getAdditionalState(getAdjointName());
  139.             return evaluateSwitchFunction(adjoint, state.getMass());
  140.         }
  141.     }

  142. }