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  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.junit.jupiter.api.Assertions;
21  import org.junit.jupiter.api.Test;
22  import org.junit.jupiter.params.ParameterizedTest;
23  import org.junit.jupiter.params.provider.ValueSource;
24  import org.mockito.Mockito;
25  import org.orekit.errors.OrekitException;
26  import org.orekit.errors.OrekitMessages;
27  import org.orekit.propagation.events.EventDetectionSettings;
28  
29  class PenalizedCartesianFuelCostTest {
30  
31      @Test
32      void testGetters() {
33          // GIVEN
34          final double expectedMagnitude = 1.;
35          final double expectedEpsilon = 0.5;
36          // WHEN
37          final TestPenalizedCost penalizedCost = new TestPenalizedCost(expectedMagnitude, expectedEpsilon);
38          // THEN
39          Assertions.assertEquals(expectedEpsilon, penalizedCost.getEpsilon());
40          Assertions.assertEquals(expectedMagnitude, penalizedCost.getMaximumThrustMagnitude());
41      }
42  
43      @Test
44      void testGetThrustDirection() {
45          // GIVEN
46          final double expectedMagnitude = 1.;
47          final double expectedEpsilon = 0.5;
48          final EventDetectionSettings expectedDetectionSettings = Mockito.mock(EventDetectionSettings.class);
49          final TestPenalizedCost penalizedCost = new TestPenalizedCost(expectedMagnitude, expectedEpsilon);
50          final double[] adjoint = new double[] {0, 0, 0, 1, 2, 3};
51          // WHEN
52          final Vector3D thrustDirection = penalizedCost.getThrustDirection(adjoint);
53          // THEN
54          Assertions.assertEquals(new Vector3D(adjoint[3], adjoint[4], adjoint[5]).normalize(), thrustDirection);
55      }
56  
57      @ParameterizedTest
58      @ValueSource(doubles = {-2, 2})
59      void testExceptionConstructor(final double outOfBoundsEpsilon) {
60          // GIVEN outOfBoundsEpsilon
61          // WHEN & THEN
62          final OrekitException exception = Assertions.assertThrows(OrekitException.class,
63                  () -> new TestPenalizedCost(1, outOfBoundsEpsilon));
64          Assertions.assertEquals(OrekitMessages.INVALID_PARAMETER_RANGE, exception.getSpecifier());
65      }
66  
67      private static class TestPenalizedCost extends PenalizedCartesianFuelCost {
68  
69          protected TestPenalizedCost(double maximumThrustMagnitude, double epsilon) {
70              super("", 0., maximumThrustMagnitude, epsilon);
71          }
72  
73          @Override
74          public double evaluatePenaltyFunction(double controlNorm) {
75              return 0;
76          }
77  
78          @Override
79          public Vector3D getThrustAccelerationVector(double[] adjointVariables, double mass) {
80              return null;
81          }
82  
83          @Override
84          public void updateAdjointDerivatives(double[] adjointVariables, double mass, double[] adjointDerivatives) {
85              // not used
86          }
87      }
88  }