1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.numerical;
18
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
24 import org.apache.commons.math3.geometry.euclidean.threed.FieldRotation;
25 import org.apache.commons.math3.geometry.euclidean.threed.FieldVector3D;
26 import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
27 import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
28 import org.apache.commons.math3.util.FastMath;
29 import org.apache.commons.math3.util.Precision;
30 import org.orekit.attitudes.Attitude;
31 import org.orekit.errors.OrekitException;
32 import org.orekit.errors.OrekitMessages;
33 import org.orekit.forces.ForceModel;
34 import org.orekit.frames.Frame;
35 import org.orekit.frames.Transform;
36 import org.orekit.orbits.CartesianOrbit;
37 import org.orekit.orbits.Orbit;
38 import org.orekit.propagation.SpacecraftState;
39 import org.orekit.time.AbsoluteDate;
40 import org.orekit.utils.PVCoordinates;
41
42
43
44
45
46
47
48
49
50
51 public class Jacobianizer {
52
53
54 private final ForceModel forceModel;
55
56
57 private final double mu;
58
59
60 private double hPos;
61
62
63 private final Map<String, Double> hParam;
64
65
66
67
68
69
70
71 public Jacobianizer(final ForceModel forceModel, final double mu,
72 final Collection<ParameterConfiguration> paramsAndSteps, final double hPos) {
73
74 this.forceModel = forceModel;
75 this.mu = mu;
76 this.hParam = new HashMap<String, Double>();
77 this.hPos = hPos;
78
79
80 for (final ParameterConfiguration param : paramsAndSteps) {
81 final String name = param.getParameterName();
82 if (forceModel.isSupported(name)) {
83 double step = param.getHP();
84 if (Double.isNaN(step)) {
85 step = FastMath.max(1.0, FastMath.abs(forceModel.getParameter(name))) *
86 FastMath.sqrt(Precision.EPSILON);
87 }
88 hParam.put(name, step);
89 }
90 }
91
92 }
93
94
95
96
97
98
99
100
101
102
103
104 private void computeShiftedAcceleration(final AccelerationRetriever retriever,
105 final AbsoluteDate date, final Frame frame,
106 final Vector3D position, final Vector3D velocity,
107 final Rotation rotation, final double mass)
108 throws OrekitException {
109 final Orbit shiftedORbit = new CartesianOrbit(new PVCoordinates(position, velocity), frame, date, mu);
110 retriever.setOrbit(shiftedORbit);
111 forceModel.addContribution(new SpacecraftState(shiftedORbit,
112 new Attitude(date, frame, rotation, Vector3D.ZERO, Vector3D.ZERO),
113 mass),
114 retriever);
115 }
116
117
118
119
120
121
122
123
124
125
126
127 public FieldVector3D<DerivativeStructure> accelerationDerivatives(final AbsoluteDate date, final Frame frame,
128 final FieldVector3D<DerivativeStructure> position,
129 final FieldVector3D<DerivativeStructure> velocity,
130 final FieldRotation<DerivativeStructure> rotation,
131 final DerivativeStructure mass)
132 throws OrekitException {
133
134 final int parameters = mass.getFreeParameters();
135 final int order = mass.getOrder();
136
137
138
139 final Vector3D p0 = position.toVector3D();
140 final Vector3D v0 = velocity.toVector3D();
141 final double r2 = p0.getNormSq();
142 final double hVel = mu * hPos / (v0.getNorm() * r2);
143
144
145 final double hMass = mass.getValue() * hPos / FastMath.sqrt(r2);
146
147
148 final AccelerationRetriever nominal = new AccelerationRetriever();
149 computeShiftedAcceleration(nominal, date, frame, p0, v0, rotation.toRotation(), mass.getValue());
150 final double[] a0 = nominal.getAcceleration().toArray();
151
152
153 final AccelerationRetriever shifted = new AccelerationRetriever();
154
155
156 computeShiftedAcceleration(shifted, date, frame, shift(position, 0, hPos), v0, shift(rotation, 0, hPos), shift(mass, 0, hPos));
157 final double[] derPx = new Vector3D(1 / hPos, shifted.getAcceleration(), -1 / hPos, nominal.getAcceleration()).toArray();
158 computeShiftedAcceleration(shifted, date, frame, shift(position, 1, hPos), v0, shift(rotation, 1, hPos), shift(mass, 1, hPos));
159 final double[] derPy = new Vector3D(1 / hPos, shifted.getAcceleration(), -1 / hPos, nominal.getAcceleration()).toArray();
160 computeShiftedAcceleration(shifted, date, frame, shift(position, 2, hPos), v0, shift(rotation, 2, hPos), shift(mass, 2, hPos));
161 final double[] derPz = new Vector3D(1 / hPos, shifted.getAcceleration(), -1 / hPos, nominal.getAcceleration()).toArray();
162
163
164 computeShiftedAcceleration(shifted, date, frame, p0, shift(velocity, 3, hVel), shift(rotation, 3, hVel), shift(mass, 3, hVel));
165 final double[] derVx = new Vector3D(1 / hVel, shifted.getAcceleration(), -1 / hVel, nominal.getAcceleration()).toArray();
166 computeShiftedAcceleration(shifted, date, frame, p0, shift(velocity, 4, hVel), shift(rotation, 4, hVel), shift(mass, 4, hVel));
167 final double[] derVy = new Vector3D(1 / hVel, shifted.getAcceleration(), -1 / hVel, nominal.getAcceleration()).toArray();
168 computeShiftedAcceleration(shifted, date, frame, p0, shift(velocity, 5, hVel), shift(rotation, 5, hVel), shift(mass, 5, hVel));
169 final double[] derVz = new Vector3D(1 / hVel, shifted.getAcceleration(), -1 / hVel, nominal.getAcceleration()).toArray();
170
171 final double[] derM;
172 if (parameters < 7) {
173 derM = null;
174 } else {
175
176 computeShiftedAcceleration(shifted, date, frame, p0, v0, shift(rotation, 6, hMass), shift(mass, 6, hMass));
177 derM = new Vector3D(1 / hMass, shifted.getAcceleration(), -1 / hMass, nominal.getAcceleration()).toArray();
178
179 }
180 final double[] derivatives = new double[1 + parameters];
181 final DerivativeStructure[] accDer = new DerivativeStructure[3];
182 for (int i = 0; i < 3; ++i) {
183
184
185 derivatives[0] = a0[i];
186
187
188 derivatives[1] = derPx[i];
189 derivatives[2] = derPy[i];
190 derivatives[3] = derPz[i];
191
192
193 derivatives[4] = derVx[i];
194 derivatives[5] = derVy[i];
195 derivatives[6] = derVz[i];
196
197 if (derM != null) {
198 derivatives[7] = derM[i];
199 }
200
201 accDer[i] = new DerivativeStructure(parameters, order, derivatives);
202
203 }
204
205 return new FieldVector3D<DerivativeStructure>(accDer);
206
207
208 }
209
210
211
212
213
214
215
216 private Vector3D shift(final FieldVector3D<DerivativeStructure> nominal, final int index, final double h) {
217 final double[] delta = new double[nominal.getX().getFreeParameters()];
218 delta[index] = h;
219 return new Vector3D(nominal.getX().taylor(delta),
220 nominal.getY().taylor(delta),
221 nominal.getZ().taylor(delta));
222 }
223
224
225
226
227
228
229
230 private Rotation shift(final FieldRotation<DerivativeStructure> nominal, final int index, final double h) {
231 final double[] delta = new double[nominal.getQ0().getFreeParameters()];
232 delta[index] = h;
233 return new Rotation(nominal.getQ0().taylor(delta),
234 nominal.getQ1().taylor(delta),
235 nominal.getQ2().taylor(delta),
236 nominal.getQ3().taylor(delta),
237 true);
238 }
239
240
241
242
243
244
245
246 private double shift(final DerivativeStructure nominal, final int index, final double h) {
247 final double[] delta = new double[nominal.getFreeParameters()];
248 delta[index] = h;
249 return nominal.taylor(delta);
250 }
251
252
253
254
255
256
257
258
259 public FieldVector3D<DerivativeStructure> accelerationDerivatives(final SpacecraftState s,
260 final String paramName)
261 throws OrekitException {
262
263 if (!hParam.containsKey(paramName)) {
264
265
266 final StringBuilder builder = new StringBuilder();
267 for (final String available : hParam.keySet()) {
268 if (builder.length() > 0) {
269 builder.append(", ");
270 }
271 builder.append(available);
272 }
273
274 throw new OrekitException(OrekitMessages.UNSUPPORTED_PARAMETER_NAME,
275 paramName, builder.toString());
276
277 }
278 final double hP = hParam.get(paramName);
279
280 final AccelerationRetriever nominal = new AccelerationRetriever();
281 nominal.setOrbit(s.getOrbit());
282 forceModel.addContribution(s, nominal);
283 final double nx = nominal.getAcceleration().getX();
284 final double ny = nominal.getAcceleration().getY();
285 final double nz = nominal.getAcceleration().getZ();
286
287 final double paramValue = forceModel.getParameter(paramName);
288 forceModel.setParameter(paramName, paramValue + hP);
289 final AccelerationRetriever shifted = new AccelerationRetriever();
290 shifted.setOrbit(s.getOrbit());
291 forceModel.addContribution(s, shifted);
292 final double sx = shifted.getAcceleration().getX();
293 final double sy = shifted.getAcceleration().getY();
294 final double sz = shifted.getAcceleration().getZ();
295
296 forceModel.setParameter(paramName, paramValue);
297
298 return new FieldVector3D<DerivativeStructure>(new DerivativeStructure(1, 1, nx, (sx - nx) / hP),
299 new DerivativeStructure(1, 1, ny, (sy - ny) / hP),
300 new DerivativeStructure(1, 1, nz, (sz - nz) / hP));
301
302 }
303
304
305 private static class AccelerationRetriever implements TimeDerivativesEquations {
306
307
308 private Vector3D acceleration;
309
310
311 private Orbit orbit;
312
313
314
315 protected AccelerationRetriever() {
316 acceleration = Vector3D.ZERO;
317 this.orbit = null;
318 }
319
320
321
322
323 public Vector3D getAcceleration() {
324 return acceleration;
325 }
326
327
328
329
330 public void setOrbit(final Orbit orbit) {
331 acceleration = Vector3D.ZERO;
332 this.orbit = orbit;
333 }
334
335
336 public void addKeplerContribution(final double mu) {
337 final Vector3D position = orbit.getPVCoordinates().getPosition();
338 final double r2 = position.getNormSq();
339 acceleration = acceleration.subtract(mu / (r2 * FastMath.sqrt(r2)), position);
340 }
341
342
343 public void addXYZAcceleration(final double x, final double y, final double z) {
344 acceleration = acceleration.add(new Vector3D(x, y, z));
345 }
346
347
348 public void addAcceleration(final Vector3D gamma, final Frame frame)
349 throws OrekitException {
350 final Transform t = frame.getTransformTo(orbit.getFrame(), orbit.getDate());
351 final Vector3D gammInRefFrame = t.transformVector(gamma);
352 addXYZAcceleration(gammInRefFrame.getX(), gammInRefFrame.getY(), gammInRefFrame.getZ());
353 }
354
355
356 public void addMassDerivative(final double q) {
357
358 }
359
360 }
361
362 }