1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.control.indirect.adjoint.cost;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22 import org.hipparchus.util.FastMath;
23 import org.orekit.propagation.FieldSpacecraftState;
24 import org.orekit.propagation.events.EventDetectionSettings;
25 import org.orekit.propagation.events.FieldEventDetectionSettings;
26 import org.orekit.propagation.events.FieldEventDetector;
27
28 import java.util.stream.Stream;
29
30
31
32
33
34
35
36
37 public class FieldQuadraticPenaltyCartesianFuel<T extends CalculusFieldElement<T>>
38 extends FieldPenalizedCartesianFuelCost<T> {
39
40
41 private final FieldEventDetectionSettings<T> eventDetectionSettings;
42
43
44
45
46
47
48
49
50
51
52 public FieldQuadraticPenaltyCartesianFuel(final String name, final T massFlowRateFactor,
53 final T maximumThrustMagnitude, final T epsilon,
54 final FieldEventDetectionSettings<T> eventDetectionSettings) {
55 super(name, massFlowRateFactor, maximumThrustMagnitude, epsilon);
56 this.eventDetectionSettings = eventDetectionSettings;
57 }
58
59
60
61
62
63
64
65
66
67 public FieldQuadraticPenaltyCartesianFuel(final String name, final T massFlowRateFactor,
68 final T maximumThrustMagnitude, final T epsilon) {
69 this(name, massFlowRateFactor, maximumThrustMagnitude, epsilon, new FieldEventDetectionSettings<>(massFlowRateFactor.getField(),
70 EventDetectionSettings.getDefaultEventDetectionSettings()));
71 }
72
73
74
75
76
77 public FieldEventDetectionSettings<T> getEventDetectionSettings() {
78 return eventDetectionSettings;
79 }
80
81
82 @Override
83 public T evaluateFieldPenaltyFunction(final T controlNorm) {
84 return controlNorm.multiply(controlNorm.multiply(getMaximumThrustMagnitude()).divide(2).subtract(1.));
85 }
86
87
88 @Override
89 public FieldVector3D<T> getFieldThrustAccelerationVector(final T[] adjointVariables, final T mass) {
90 final T switchFunction = evaluateSwitchFunction(adjointVariables, mass);
91 if (switchFunction.getReal() > 0) {
92 final T thrustForceMagnitude = FastMath.min(switchFunction, getMaximumThrustMagnitude());
93 return getFieldThrustDirection(adjointVariables).scalarMultiply(thrustForceMagnitude.divide(mass));
94 } else {
95 return FieldVector3D.getZero(mass.getField());
96 }
97 }
98
99
100 @Override
101 public void updateFieldAdjointDerivatives(final T[] adjointVariables, final T mass, final T[] adjointDerivatives) {
102 if (getAdjointDimension() > 6) {
103 final T switchFunction = evaluateSwitchFunction(adjointVariables, mass);
104 if (switchFunction.getReal() > 0.) {
105 final T minimum = FastMath.min(switchFunction, getMaximumThrustMagnitude());
106 adjointDerivatives[6] = adjointDerivatives[6].add(getFieldAdjointVelocityNorm(adjointVariables)
107 .multiply(minimum).divide(mass.square()));
108 }
109 }
110 }
111
112
113
114
115
116
117
118 private T evaluateSwitchFunction(final T[] adjointVariables, final T mass) {
119 T epsilonIndependentTerm = getFieldAdjointVelocityNorm(adjointVariables).divide(mass).subtract(1.);
120 if (getAdjointDimension() > 6) {
121 epsilonIndependentTerm = epsilonIndependentTerm.subtract(adjointVariables[6].multiply(getMassFlowRateFactor()));
122 }
123 return epsilonIndependentTerm.divide(getEpsilon()).add(1);
124 }
125
126
127 @Override
128 public Stream<FieldEventDetector<T>> getFieldEventDetectors(final Field<T> field) {
129 return Stream.of(new FieldQuadraticPenalizedSwitchDetector(getEventDetectionSettings(), field.getZero()),
130 new FieldQuadraticPenalizedSwitchDetector(getEventDetectionSettings(), getMaximumThrustMagnitude()));
131 }
132
133
134
135
136 private class FieldQuadraticPenalizedSwitchDetector extends FieldControlSwitchDetector<T> {
137
138
139 private final T criticalValue;
140
141
142
143
144
145
146 FieldQuadraticPenalizedSwitchDetector(final FieldEventDetectionSettings<T> detectionSettings,
147 final T criticalValue) {
148 super(detectionSettings);
149 this.criticalValue = criticalValue;
150 }
151
152
153 @Override
154 public T g(final FieldSpacecraftState<T> state) {
155 final T[] adjoint = state.getAdditionalState(getAdjointName());
156 return evaluateSwitchFunction(adjoint, state.getMass()).subtract(criticalValue);
157 }
158 }
159
160
161 @Override
162 public QuadraticPenaltyCartesianFuel toCartesianCost() {
163 return new QuadraticPenaltyCartesianFuel(getAdjointName(), getMassFlowRateFactor().getReal(),
164 getMaximumThrustMagnitude().getReal(), getEpsilon().getReal(),
165 getEventDetectionSettings().toEventDetectionSettings());
166 }
167 }