1 /* Copyright 2002-2025 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.utils;
18
19 import org.hipparchus.analysis.differentiation.Derivative;
20 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
21 import org.hipparchus.geometry.euclidean.threed.Vector3D;
22 import org.orekit.annotation.DefaultDataContext;
23 import org.orekit.data.DataContext;
24 import org.orekit.frames.Frame;
25 import org.orekit.time.AbsoluteDate;
26 import org.orekit.time.TimeOffset;
27 import org.orekit.time.TimeScale;
28 import org.orekit.time.TimeStamped;
29
30 /** {@link TimeStamped time-stamped} version of {@link PVCoordinates}.
31 * <p>Instances of this class are guaranteed to be immutable.</p>
32 * @author Luc Maisonobe
33 * @since 7.0
34 */
35 public class TimeStampedPVCoordinates extends PVCoordinates implements TimeStamped {
36
37 /** The date. */
38 private final AbsoluteDate date;
39
40 /** Builds a TimeStampedPVCoordinates pair.
41 * @param date coordinates date
42 * @param position the position vector (m)
43 * @param velocity the velocity vector (m/s)
44 * @param acceleration the acceleration vector (m/s²)
45 */
46 public TimeStampedPVCoordinates(final AbsoluteDate date,
47 final Vector3D position, final Vector3D velocity, final Vector3D acceleration) {
48 super(position, velocity, acceleration);
49 this.date = date;
50 }
51
52 /**
53 * Build from position and velocity. Acceleration is set to zero.
54 *
55 * @param date coordinates date
56 * @param position the position vector (m)
57 * @param velocity the velocity vector (m/s)
58 */
59 public TimeStampedPVCoordinates(final AbsoluteDate date,
60 final Vector3D position,
61 final Vector3D velocity) {
62 this(date, position, velocity, Vector3D.ZERO);
63 }
64
65 /**
66 * Build from position velocity acceleration coordinates.
67 *
68 * @param date coordinates date
69 * @param pv position velocity, and acceleration coordinates, in meters and seconds.
70 */
71 public TimeStampedPVCoordinates(final AbsoluteDate date, final PVCoordinates pv) {
72 this(date, pv.getPosition(), pv.getVelocity(), pv.getAcceleration());
73 }
74
75 /** Multiplicative constructor
76 * <p>Build a TimeStampedPVCoordinates from another one and a scale factor.</p>
77 * <p>The TimeStampedPVCoordinates built will be a * pv</p>
78 * @param date date of the built coordinates
79 * @param a scale factor
80 * @param pv base (unscaled) PVCoordinates
81 */
82 public TimeStampedPVCoordinates(final AbsoluteDate date,
83 final double a, final PVCoordinates pv) {
84 super(new Vector3D(a, pv.getPosition()),
85 new Vector3D(a, pv.getVelocity()),
86 new Vector3D(a, pv.getAcceleration()));
87 this.date = date;
88 }
89
90 /** Subtractive constructor
91 * <p>Build a relative TimeStampedPVCoordinates from a start and an end position.</p>
92 * <p>The TimeStampedPVCoordinates built will be end - start.</p>
93 * @param date date of the built coordinates
94 * @param start Starting PVCoordinates
95 * @param end ending PVCoordinates
96 */
97 public TimeStampedPVCoordinates(final AbsoluteDate date,
98 final PVCoordinates start, final PVCoordinates end) {
99 super(end.getPosition().subtract(start.getPosition()),
100 end.getVelocity().subtract(start.getVelocity()),
101 end.getAcceleration().subtract(start.getAcceleration()));
102 this.date = date;
103 }
104
105 /** Linear constructor
106 * <p>Build a TimeStampedPVCoordinates from two other ones and corresponding scale factors.</p>
107 * <p>The TimeStampedPVCoordinates built will be a1 * u1 + a2 * u2</p>
108 * @param date date of the built coordinates
109 * @param a1 first scale factor
110 * @param pv1 first base (unscaled) PVCoordinates
111 * @param a2 second scale factor
112 * @param pv2 second base (unscaled) PVCoordinates
113 */
114 public TimeStampedPVCoordinates(final AbsoluteDate date,
115 final double a1, final PVCoordinates pv1,
116 final double a2, final PVCoordinates pv2) {
117 super(new Vector3D(a1, pv1.getPosition(), a2, pv2.getPosition()),
118 new Vector3D(a1, pv1.getVelocity(), a2, pv2.getVelocity()),
119 new Vector3D(a1, pv1.getAcceleration(), a2, pv2.getAcceleration()));
120 this.date = date;
121 }
122
123 /** Linear constructor
124 * <p>Build a TimeStampedPVCoordinates from three other ones and corresponding scale factors.</p>
125 * <p>The TimeStampedPVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
126 * @param date date of the built coordinates
127 * @param a1 first scale factor
128 * @param pv1 first base (unscaled) PVCoordinates
129 * @param a2 second scale factor
130 * @param pv2 second base (unscaled) PVCoordinates
131 * @param a3 third scale factor
132 * @param pv3 third base (unscaled) PVCoordinates
133 */
134 public TimeStampedPVCoordinates(final AbsoluteDate date,
135 final double a1, final PVCoordinates pv1,
136 final double a2, final PVCoordinates pv2,
137 final double a3, final PVCoordinates pv3) {
138 super(new Vector3D(a1, pv1.getPosition(), a2, pv2.getPosition(), a3, pv3.getPosition()),
139 new Vector3D(a1, pv1.getVelocity(), a2, pv2.getVelocity(), a3, pv3.getVelocity()),
140 new Vector3D(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(), a3, pv3.getAcceleration()));
141 this.date = date;
142 }
143
144 /** Linear constructor
145 * <p>Build a TimeStampedPVCoordinates from four other ones and corresponding scale factors.</p>
146 * <p>The TimeStampedPVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
147 * @param date date of the built coordinates
148 * @param a1 first scale factor
149 * @param pv1 first base (unscaled) PVCoordinates
150 * @param a2 second scale factor
151 * @param pv2 second base (unscaled) PVCoordinates
152 * @param a3 third scale factor
153 * @param pv3 third base (unscaled) PVCoordinates
154 * @param a4 fourth scale factor
155 * @param pv4 fourth base (unscaled) PVCoordinates
156 */
157 public TimeStampedPVCoordinates(final AbsoluteDate date,
158 final double a1, final PVCoordinates pv1,
159 final double a2, final PVCoordinates pv2,
160 final double a3, final PVCoordinates pv3,
161 final double a4, final PVCoordinates pv4) {
162 super(new Vector3D(a1, pv1.getPosition(), a2, pv2.getPosition(), a3, pv3.getPosition(), a4, pv4.getPosition()),
163 new Vector3D(a1, pv1.getVelocity(), a2, pv2.getVelocity(), a3, pv3.getVelocity(), a4, pv4.getVelocity()),
164 new Vector3D(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(), a3, pv3.getAcceleration(), a4, pv4.getAcceleration()));
165 this.date = date;
166 }
167
168 /** Builds a TimeStampedPVCoordinates triplet from a {@link FieldVector3D}<{@link Derivative}>.
169 * <p>
170 * The vector components must have time as their only derivation parameter and
171 * have consistent derivation orders.
172 * </p>
173 * @param date date of the built coordinates
174 * @param p vector with time-derivatives embedded within the coordinates
175 * @param <U> type of the derivative
176 */
177 public <U extends Derivative<U>> TimeStampedPVCoordinates(final AbsoluteDate date, final FieldVector3D<U> p) {
178 super(p);
179 this.date = date;
180 }
181
182 /** {@inheritDoc} */
183 public AbsoluteDate getDate() {
184 return date;
185 }
186
187 /** Get a time-shifted state.
188 * <p>
189 * The state can be slightly shifted to close dates. This shift is based on
190 * a simple Taylor expansion. It is <em>not</em> intended as a replacement for
191 * proper orbit propagation (it is not even Keplerian!) but should be sufficient
192 * for either small time shifts or coarse accuracy.
193 * </p>
194 * @param dt time shift in seconds
195 * @return a new state, shifted with respect to the instance (which is immutable)
196 */
197 @Override
198 public TimeStampedPVCoordinates shiftedBy(final double dt) {
199 final PVCoordinates spv = super.shiftedBy(dt);
200 return new TimeStampedPVCoordinates(date.shiftedBy(dt),
201 spv.getPosition(), spv.getVelocity(), spv.getAcceleration());
202 }
203
204 /** Get a time-shifted state.
205 * <p>
206 * The state can be slightly shifted to close dates. This shift is based on
207 * a simple Taylor expansion. It is <em>not</em> intended as a replacement for
208 * proper orbit propagation (it is not even Keplerian!) but should be sufficient
209 * for either small time shifts or coarse accuracy.
210 * </p>
211 * @param dt time shift
212 * @return a new state, shifted with respect to the instance (which is immutable)
213 * @since 13.0
214 */
215 @Override
216 public TimeStampedPVCoordinates shiftedBy(final TimeOffset dt) {
217 final PVCoordinates spv = super.shiftedBy(dt);
218 return new TimeStampedPVCoordinates(date.shiftedBy(dt),
219 spv.getPosition(), spv.getVelocity(), spv.getAcceleration());
220 }
221
222 /** Create a local provider using simply Taylor expansion through {@link #shiftedBy(double)}.
223 * <p>
224 * The time evolution is based on a simple Taylor expansion. It is <em>not</em> intended as a
225 * replacement for proper orbit propagation (it is not even Keplerian!) but should be sufficient
226 * for either small time shifts or coarse accuracy.
227 * </p>
228 * @param instanceFrame frame in which the instance is defined
229 * @return provider based on Taylor expansion, for small time shifts around instance date
230 */
231 public PVCoordinatesProvider toTaylorProvider(final Frame instanceFrame) {
232 return new ShiftingPVCoordinatesProvider(this, instanceFrame);
233 }
234
235 /** Return a string representation of this date, position, velocity, and acceleration.
236 *
237 * <p>This method uses the {@link DataContext#getDefault() default data context}.
238 *
239 * @return string representation of this.
240 */
241 @Override
242 @DefaultDataContext
243 public String toString() {
244 return toString(DataContext.getDefault().getTimeScales().getUTC());
245 }
246
247 /**
248 * Return a string representation of this date, position, velocity, and acceleration.
249 *
250 * @param utc time scale used to print the date.
251 * @return string representation of this.
252 */
253 public String toString(final TimeScale utc) {
254 final String comma = ", ";
255 return new StringBuilder().append('{').
256 append(date.toString(utc)).append(", P(").
257 append(getPosition().getX()).append(comma).
258 append(getPosition().getY()).append(comma).
259 append(getPosition().getZ()).append("), V(").
260 append(getVelocity().getX()).append(comma).
261 append(getVelocity().getY()).append(comma).
262 append(getVelocity().getZ()).append("), A(").
263 append(getAcceleration().getX()).append(comma).
264 append(getAcceleration().getY()).append(comma).
265 append(getAcceleration().getZ()).append(")}").toString();
266 }
267
268 }