1 /* Copyright 2002-2026 CS GROUP
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.propagation.relative;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
21 import org.orekit.frames.Frame;
22 import org.orekit.time.FieldAbsoluteDate;
23 import org.orekit.time.TimeUtils;
24 import org.orekit.utils.FieldPVCoordinates;
25 import org.orekit.utils.TimeStampedFieldPVCoordinates;
26
27 /**
28 * This class stores the solution of a two-impulse rendez-vous. All the contained variables are expressed in the same
29 * frame, accessible through the method getFrame(). Since the PVT of the chaser on both ends of the transfer orbit are
30 * stored in this object in addition to the ΔV vectors, it is possible to reconstruct the orbit of the chaser before and
31 * after the transfer.
32 *
33 * @param <T> Any scalar field
34 *
35 * @author Jérôme Tabeaud
36 * @author Romain Cuvillon
37 * @since 14.0
38 */
39 public class FieldTwoImpulseTransfer<T extends CalculusFieldElement<T>> {
40
41 /**
42 * PVT of the chaser just after the first maneuver.
43 */
44 private final TimeStampedFieldPVCoordinates<T> pvt1;
45
46 /**
47 * PVT of the chaser just before the second maneuver.
48 */
49 private final TimeStampedFieldPVCoordinates<T> pvt2;
50
51 /**
52 * ΔV vector of first maneuver.
53 */
54 private final FieldVector3D<T> deltaV1;
55
56 /**
57 * ΔV vector of second maneuver.
58 */
59 private final FieldVector3D<T> deltaV2;
60
61 /**
62 * Frame in which the PVT and ΔV are expressed.
63 */
64 private final Frame frame;
65
66 /**
67 * Creates a new TwoImpulseTransfer object from the given PVT and ΔV vectors.
68 *
69 * @param pvt1 PVT at the start of the transfer
70 * @param pvt2 PVT at the end of the transfer
71 * @param deltaV1 ΔV to enter the transfer orbit
72 * @param deltaV2 ΔV to exit the transfer orbit
73 * @param frame Frame in which the PVT and ΔV vector are expressed
74 */
75 public FieldTwoImpulseTransfer(final TimeStampedFieldPVCoordinates<T> pvt1,
76 final TimeStampedFieldPVCoordinates<T> pvt2,
77 final FieldVector3D<T> deltaV1,
78 final FieldVector3D<T> deltaV2,
79 final Frame frame) {
80 this.pvt1 = pvt1;
81 this.pvt2 = pvt2;
82 this.deltaV1 = deltaV1;
83 this.deltaV2 = deltaV2;
84 this.frame = frame;
85 }
86
87 /**
88 * Creates a new {@link TwoImpulseTransfer} object from the given PVT before the first maneuver and after the second
89 * maneuver (on the initial and final orbits), as well as the velocity vectors after the first maneuver and before
90 * the second maneuver (on the transfer orbit).
91 *
92 * @param pvt1BeforeMan PVT before the departure maneuver
93 * @param v1AfterMan Velocity after the departure maneuver
94 * @param pvt2AfterMan PVT after the rendez-vous maneuver
95 * @param v2BeforeMan Velocity before the rendez-vous maneuver
96 * @param inputFrame Frame in which the PVT and velocity vectors are expressed
97 * @return TwoImpulseTransfer object that corresponds to the inputs
98 */
99 public FieldTwoImpulseTransfer<T> fromPVTAndVelocities(final TimeStampedFieldPVCoordinates<T> pvt1BeforeMan,
100 final FieldVector3D<T> v1AfterMan,
101 final TimeStampedFieldPVCoordinates<T> pvt2AfterMan,
102 final FieldVector3D<T> v2BeforeMan,
103 final Frame inputFrame) {
104 final TimeStampedFieldPVCoordinates<T> pvt1AfterMan =
105 new TimeStampedFieldPVCoordinates<>(pvt1BeforeMan.getDate(),
106 new FieldPVCoordinates<>(pvt1BeforeMan.getPosition(),
107 v1AfterMan));
108 final TimeStampedFieldPVCoordinates<T> pvt2BeforeMan =
109 new TimeStampedFieldPVCoordinates<>(pvt2AfterMan.getDate(),
110 new FieldPVCoordinates<>(pvt2AfterMan.getPosition(),
111 v2BeforeMan));
112 final FieldVector3D<T> delta_V1 = pvt1AfterMan.getVelocity().subtract(pvt1BeforeMan.getVelocity());
113 final FieldVector3D<T> delta_V2 = pvt2AfterMan.getVelocity().subtract(pvt2BeforeMan.getVelocity());
114 return new FieldTwoImpulseTransfer<>(pvt1AfterMan, pvt2BeforeMan, delta_V1, delta_V2, inputFrame);
115 }
116
117 /**
118 * Gets the PVT of the chaser just after the first maneuver, i.e. at the start of the transfer orbit.
119 *
120 * @return PVT of the chaser just after the first maneuver
121 */
122 public TimeStampedFieldPVCoordinates<T> getPvt1() {
123 return pvt1;
124 }
125
126 /**
127 * Gets the PVT of the chaser just before the second maneuver, i.e. at the end of the transfer orbit.
128 *
129 * @return PVT of the chaser just before the second maneuver
130 */
131 public TimeStampedFieldPVCoordinates<T> getPvt2() {
132 return pvt2;
133 }
134
135 /**
136 * Gets the ΔV vector of the first maneuver.
137 *
138 * @return The ΔV vector of first maneuver
139 */
140 public FieldVector3D<T> getDeltaV1() {
141 return deltaV1;
142 }
143
144 /**
145 * Get the ΔV vector of the second maneuver.
146 *
147 * @return The ΔV vector of second maneuver
148 */
149 public FieldVector3D<T> getDeltaV2() {
150 return deltaV2;
151 }
152
153 /**
154 * Get the PVT of the chaser just after the first maneuver expressed in the given frame.
155 *
156 * @param outputFrame given frame for the first maneuver
157 * @return PVT of the chaser just after the first maneuver
158 */
159 public TimeStampedFieldPVCoordinates<T> getPvt1(final Frame outputFrame) {
160 return frame.getTransformTo(outputFrame, pvt1.getDate()).transformPVCoordinates(pvt1);
161 }
162
163 /**
164 * Get the PVT of the chaser just before the second maneuver expressed in the given frame.
165 *
166 * @param outputFrame given frame for the 2nd maneuver
167 * @return PVT of the chaser just before the second maneuver
168 */
169 public TimeStampedFieldPVCoordinates<T> getPvt2(final Frame outputFrame) {
170 return frame.getTransformTo(outputFrame, pvt2.getDate()).transformPVCoordinates(pvt2);
171 }
172
173 /**
174 * Get the ΔV vector of first maneuver in the given frame.
175 *
176 * @param outputFrame given frame for the first maneuver
177 * @return The ΔV vector of first maneuver in the given frame at the given date
178 */
179 public FieldVector3D<T> getDeltaV1(final Frame outputFrame) {
180 return frame.getTransformTo(outputFrame, pvt1.getDate()).transformVector(deltaV1);
181 }
182
183 /**
184 * Get the ΔV vector of second maneuver in the given frame.
185 *
186 * @param outputFrame given frame for the 2nd maneuver
187 * @return The ΔV vector of second maneuver in the given frame at the given date
188 */
189 public FieldVector3D<T> getDeltaV2(final Frame outputFrame) {
190 return frame.getTransformTo(outputFrame, pvt2.getDate()).transformVector(deltaV2);
191 }
192
193 /**
194 * Computes the total ΔV of the transfer.
195 *
196 * @return ||ΔV_total|| = ||ΔV1|| + ||ΔV2||
197 */
198 public T getTotalDeltaV() {
199 return deltaV1.getNorm().add(deltaV2.getNorm());
200 }
201
202 /**
203 * Returns the duration of the transfer between the two impulses.
204 * @return The duration of the transfer between the two impulses
205 */
206 public T getDuration() {
207 return pvt2.durationFrom(pvt1);
208 }
209
210 /**
211 * Returns the departure date.
212 *
213 * @return the departure date
214 */
215 public FieldAbsoluteDate<T> getDepartureDate() {
216 return pvt1.getDate();
217 }
218
219 /**
220 * Returns the arrival date.
221 *
222 * @return the arrival date
223 */
224 public FieldAbsoluteDate<T> getArrivalDate() {
225 return pvt2.getDate();
226 }
227
228 /**
229 * Returns the frame in which all elements contained in the object are expressed.
230 *
231 * @return The frame of the elements of the object
232 */
233 public Frame getFrame() {
234 return frame;
235 }
236
237 /**
238 * Get the PVT before the injection maneuver into the transfer orbit.
239 *
240 * @return The PVT before the injection maneuver into the transfer orbit
241 */
242 public TimeStampedFieldPVCoordinates<T> getPvt1BeforeMan() {
243 return new TimeStampedFieldPVCoordinates<>(pvt1.getDate(),
244 new FieldPVCoordinates<>(pvt1.getPosition(),
245 pvt1.getVelocity().subtract(deltaV1)));
246 }
247
248 /**
249 * Get the PVT after the velocity-synchronization maneuver into the target orbit.
250 *
251 * @return The PVT after the velocity-synchronization maneuver into the target orbit
252 */
253 public TimeStampedFieldPVCoordinates<T> getPvt2AfterMan() {
254 return new TimeStampedFieldPVCoordinates<>(pvt2.getDate(),
255 new FieldPVCoordinates<>(pvt2.getPosition(),
256 pvt2.getVelocity().add(deltaV2)));
257 }
258
259 /**
260 * Converts all the PVT and ΔV vectors to the desired frame.
261 *
262 * @param outputFrame Desired output frame
263 * @return TwoImpulseTransfer object expressed in the desired frame
264 */
265 public FieldTwoImpulseTransfer<T> expressInFrame(final Frame outputFrame) {
266 return new FieldTwoImpulseTransfer<>(getPvt1(outputFrame),
267 getPvt2(outputFrame),
268 getDeltaV1(outputFrame),
269 getDeltaV2(outputFrame),
270 outputFrame);
271 }
272
273 /**
274 * Writes a string summarizing the transfer characteristics (PVT and ΔV vectors).
275 * <p>
276 * Only the real value is printed, not the field one.
277 * </p>
278 *
279 * @return The string summary
280 */
281 public String toString() {
282 return "Two impulse transfer\n" +
283 "\n Frame: " + getFrame().getName() +
284 "\n PVT after first manoeuvre: " + getPvt1() +
285 "\n PVT before second manoeuvre: " + getPvt2() +
286 "\n ΔV of first manoeuvre: " + getDeltaV1() + " ; ‖ΔV₁‖ = " + getDeltaV1().getNorm() +
287 "\n ΔV of second manoeuvre: " + getDeltaV2() + " ; ‖ΔV₂‖ = " + getDeltaV2().getNorm() +
288 "\n Total ΔV: " + getTotalDeltaV() +
289 "\n Duration: " + TimeUtils.secondsToDHMS(getDuration().getReal()) + "\n";
290 }
291 }