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