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
20 import org.hipparchus.geometry.euclidean.threed.Vector3D;
21 import org.orekit.propagation.SpacecraftState;
22 import org.orekit.propagation.events.EventDetectionSettings;
23 import org.orekit.propagation.events.EventDetector;
24
25 import java.util.stream.Stream;
26
27
28
29
30
31
32
33
34
35 public class CartesianFuelCost extends AbstractCartesianCost {
36
37
38 private final double maximumThrustMagnitude;
39
40
41 private final EventDetectionSettings eventDetectionSettings;
42
43
44
45
46
47
48
49 public CartesianFuelCost(final String name, final double massFlowRateFactor, final double maximumThrustMagnitude) {
50 this(name, massFlowRateFactor, maximumThrustMagnitude, EventDetectionSettings.getDefaultEventDetectionSettings());
51 }
52
53
54
55
56
57
58
59
60 public CartesianFuelCost(final String name, final double massFlowRateFactor, final double maximumThrustMagnitude,
61 final EventDetectionSettings eventDetectionSettings) {
62 super(name, massFlowRateFactor);
63 this.maximumThrustMagnitude = maximumThrustMagnitude;
64 this.eventDetectionSettings = eventDetectionSettings;
65 }
66
67
68
69
70 public double getMaximumThrustMagnitude() {
71 return maximumThrustMagnitude;
72 }
73
74
75
76
77
78 public EventDetectionSettings getEventDetectionSettings() {
79 return eventDetectionSettings;
80 }
81
82
83
84
85
86
87
88 private double evaluateSwitchFunction(final double[] adjointVariables, final double mass) {
89 double switchFunction = getAdjointVelocityNorm(adjointVariables) / mass - 1.;
90 if (getAdjointDimension() > 6) {
91 switchFunction -= adjointVariables[6] * getMassFlowRateFactor();
92 }
93 return switchFunction;
94 }
95
96
97
98
99
100
101 private Vector3D getThrustDirection(final double[] adjointVariables) {
102 return new Vector3D(adjointVariables[3], adjointVariables[4], adjointVariables[5]).normalize();
103 }
104
105
106 @Override
107 public Vector3D getThrustAccelerationVector(final double[] adjointVariables, final double mass) {
108 final double switchFunction = evaluateSwitchFunction(adjointVariables, mass);
109 if (switchFunction > 0.) {
110 return getThrustDirection(adjointVariables).scalarMultiply(maximumThrustMagnitude / mass);
111 } else {
112 return Vector3D.ZERO;
113 }
114 }
115
116
117 @Override
118 public void updateAdjointDerivatives(final double[] adjointVariables, final double mass,
119 final double[] adjointDerivatives) {
120 if (getAdjointDimension() > 6) {
121 final double switchFunction = evaluateSwitchFunction(adjointVariables, mass);
122 if (switchFunction > 0.) {
123 adjointDerivatives[6] += getAdjointVelocityNorm(adjointVariables) * maximumThrustMagnitude / (mass * mass);
124 }
125 }
126 }
127
128
129 @Override
130 public double getHamiltonianContribution(final double[] adjointVariables, final double mass) {
131 final Vector3D thrustForce = getThrustAccelerationVector(adjointVariables, mass).scalarMultiply(mass);
132 return -thrustForce.getNorm();
133 }
134
135
136 @Override
137 public Stream<EventDetector> getEventDetectors() {
138 return Stream.of(new FuelCostSwitchDetector(eventDetectionSettings));
139 }
140
141
142
143
144 private class FuelCostSwitchDetector extends ControlSwitchDetector {
145
146
147
148
149
150 FuelCostSwitchDetector(final EventDetectionSettings detectionSettings) {
151 super(detectionSettings);
152 }
153
154
155 @Override
156 public double g(final SpacecraftState state) {
157 final double[] adjoint = state.getAdditionalState(getAdjointName());
158 return evaluateSwitchFunction(adjoint, state.getMass());
159 }
160 }
161
162 }