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.errors.OrekitException; 23 import org.orekit.errors.OrekitIllegalArgumentException; 24 import org.orekit.errors.OrekitMessages; 25 import org.orekit.frames.Frame; 26 import org.orekit.frames.StaticTransform; 27 import org.orekit.frames.Transform; 28 import org.orekit.time.AbsoluteDate; 29 import org.orekit.time.TimeOffset; 30 import org.orekit.time.TimeStamped; 31 32 /** Position - Velocity - Acceleration linked to a date and a frame. 33 */ 34 public class AbsolutePVCoordinates extends TimeStampedPVCoordinates implements TimeStamped, PVCoordinatesProvider { 35 36 /** Frame in which are defined the coordinates. */ 37 private final Frame frame; 38 39 /** Build from position, velocity, acceleration. 40 * @param frame the frame in which the coordinates are defined 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 AbsolutePVCoordinates(final Frame frame, final AbsoluteDate date, 47 final Vector3D position, final Vector3D velocity, final Vector3D acceleration) { 48 super(date, position, velocity, acceleration); 49 this.frame = frame; 50 } 51 52 /** Build from position and velocity. Acceleration is set to zero. 53 * @param frame the frame in which the coordinates are defined 54 * @param date coordinates date 55 * @param position the position vector (m) 56 * @param velocity the velocity vector (m/s) 57 */ 58 public AbsolutePVCoordinates(final Frame frame, final AbsoluteDate date, 59 final Vector3D position, 60 final Vector3D velocity) { 61 this(frame, date, position, velocity, Vector3D.ZERO); 62 } 63 64 /** Build from frame, date and PVA coordinates. 65 * @param frame the frame in which the coordinates are defined 66 * @param date date of the coordinates 67 * @param pva TimeStampedPVCoordinates 68 */ 69 public AbsolutePVCoordinates(final Frame frame, final AbsoluteDate date, final PVCoordinates pva) { 70 super(date, pva); 71 this.frame = frame; 72 } 73 74 /** Build from frame and TimeStampedPVCoordinates. 75 * @param frame the frame in which the coordinates are defined 76 * @param pva TimeStampedPVCoordinates 77 */ 78 public AbsolutePVCoordinates(final Frame frame, final TimeStampedPVCoordinates pva) { 79 super(pva.getDate(), pva); 80 this.frame = frame; 81 } 82 83 /** Multiplicative constructor 84 * <p>Build a AbsolutePVCoordinates from another one and a scale factor.</p> 85 * <p>The TimeStampedPVCoordinates built will be a * AbsPva</p> 86 * @param date date of the built coordinates 87 * @param a scale factor 88 * @param AbsPva base (unscaled) AbsolutePVCoordinates 89 */ 90 public AbsolutePVCoordinates(final AbsoluteDate date, 91 final double a, final AbsolutePVCoordinates AbsPva) { 92 super(date, a, AbsPva); 93 this.frame = AbsPva.frame; 94 } 95 96 /** Subtractive constructor 97 * <p>Build a relative AbsolutePVCoordinates from a start and an end position.</p> 98 * <p>The AbsolutePVCoordinates built will be end - start.</p> 99 * <p>In case start and end use two different pseudo-inertial frames, 100 * the new AbsolutePVCoordinates arbitrarily be defined in the start frame. </p> 101 * @param date date of the built coordinates 102 * @param start Starting AbsolutePVCoordinates 103 * @param end ending AbsolutePVCoordinates 104 */ 105 public AbsolutePVCoordinates(final AbsoluteDate date, 106 final AbsolutePVCoordinates start, final AbsolutePVCoordinates end) { 107 super(date, start, end); 108 ensureIdenticalFrames(start, end); 109 this.frame = start.frame; 110 } 111 112 /** Linear constructor 113 * <p>Build a AbsolutePVCoordinates from two other ones and corresponding scale factors.</p> 114 * <p>The AbsolutePVCoordinates built will be a1 * u1 + a2 * u2</p> 115 * <p>In case the AbsolutePVCoordinates use different pseudo-inertial frames, 116 * the new AbsolutePVCoordinates arbitrarily be defined in the first frame. </p> 117 * @param date date of the built coordinates 118 * @param a1 first scale factor 119 * @param absPv1 first base (unscaled) AbsolutePVCoordinates 120 * @param a2 second scale factor 121 * @param absPv2 second base (unscaled) AbsolutePVCoordinates 122 */ 123 public AbsolutePVCoordinates(final AbsoluteDate date, 124 final double a1, final AbsolutePVCoordinates absPv1, 125 final double a2, final AbsolutePVCoordinates absPv2) { 126 super(date, a1, absPv1.getPVCoordinates(), a2, absPv2.getPVCoordinates()); 127 ensureIdenticalFrames(absPv1, absPv2); 128 this.frame = absPv1.getFrame(); 129 } 130 131 /** Linear constructor 132 * <p>Build a AbsolutePVCoordinates from three other ones and corresponding scale factors.</p> 133 * <p>The AbsolutePVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p> 134 * <p>In case the AbsolutePVCoordinates use different pseudo-inertial frames, 135 * the new AbsolutePVCoordinates arbitrarily be defined in the first frame. </p> 136 * @param date date of the built coordinates 137 * @param a1 first scale factor 138 * @param absPv1 first base (unscaled) AbsolutePVCoordinates 139 * @param a2 second scale factor 140 * @param absPv2 second base (unscaled) AbsolutePVCoordinates 141 * @param a3 third scale factor 142 * @param absPv3 third base (unscaled) AbsolutePVCoordinates 143 */ 144 public AbsolutePVCoordinates(final AbsoluteDate date, 145 final double a1, final AbsolutePVCoordinates absPv1, 146 final double a2, final AbsolutePVCoordinates absPv2, 147 final double a3, final AbsolutePVCoordinates absPv3) { 148 super(date, a1, absPv1.getPVCoordinates(), a2, absPv2.getPVCoordinates(), 149 a3, absPv3.getPVCoordinates()); 150 ensureIdenticalFrames(absPv1, absPv2); 151 ensureIdenticalFrames(absPv1, absPv3); 152 this.frame = absPv1.getFrame(); 153 } 154 155 /** Linear constructor 156 * <p>Build a AbsolutePVCoordinates from four other ones and corresponding scale factors.</p> 157 * <p>The AbsolutePVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p> 158 * <p>In case the AbsolutePVCoordinates use different pseudo-inertial frames, 159 * the new AbsolutePVCoordinates arbitrarily be defined in the first frame. </p> 160 * @param date date of the built coordinates 161 * @param a1 first scale factor 162 * @param absPv1 first base (unscaled) AbsolutePVCoordinates 163 * @param a2 second scale factor 164 * @param absPv2 second base (unscaled) AbsolutePVCoordinates 165 * @param a3 third scale factor 166 * @param absPv3 third base (unscaled) AbsolutePVCoordinates 167 * @param a4 fourth scale factor 168 * @param absPv4 fourth base (unscaled) AbsolutePVCoordinates 169 */ 170 public AbsolutePVCoordinates(final AbsoluteDate date, 171 final double a1, final AbsolutePVCoordinates absPv1, 172 final double a2, final AbsolutePVCoordinates absPv2, 173 final double a3, final AbsolutePVCoordinates absPv3, 174 final double a4, final AbsolutePVCoordinates absPv4) { 175 super(date, a1, absPv1.getPVCoordinates(), a2, absPv2.getPVCoordinates(), 176 a3, absPv3.getPVCoordinates(), a4, absPv4.getPVCoordinates()); 177 ensureIdenticalFrames(absPv1, absPv2); 178 ensureIdenticalFrames(absPv1, absPv3); 179 ensureIdenticalFrames(absPv1, absPv4); 180 this.frame = absPv1.getFrame(); 181 } 182 183 /** Builds a AbsolutePVCoordinates triplet from a {@link FieldVector3D}<{@link Derivative}>. 184 * <p> 185 * The vector components must have time as their only derivation parameter and 186 * have consistent derivation orders. 187 * </p> 188 * @param frame the frame in which the parameters are defined 189 * @param date date of the built coordinates 190 * @param p vector with time-derivatives embedded within the coordinates 191 * @param <U> type of the derivative 192 */ 193 public <U extends Derivative<U>> AbsolutePVCoordinates(final Frame frame, final AbsoluteDate date, 194 final FieldVector3D<U> p) { 195 super(date, p); 196 this.frame = frame; 197 } 198 199 /** Ensure that the frames from two AbsolutePVCoordinates are identical. 200 * @param absPv1 first AbsolutePVCoordinates 201 * @param absPv2 first AbsolutePVCoordinates 202 * @throws OrekitIllegalArgumentException if frames are different 203 */ 204 private static void ensureIdenticalFrames(final AbsolutePVCoordinates absPv1, final AbsolutePVCoordinates absPv2) 205 throws OrekitIllegalArgumentException { 206 if (!absPv1.frame.equals(absPv2.frame)) { 207 throw new OrekitIllegalArgumentException(OrekitMessages.INCOMPATIBLE_FRAMES, 208 absPv1.frame.getName(), absPv2.frame.getName()); 209 } 210 } 211 212 /** Get a time-shifted state. 213 * <p> 214 * The state can be slightly shifted to close dates. This shift is based on 215 * a simple Taylor expansion. It is <em>not</em> intended as a replacement for 216 * proper orbit propagation (it is not even Keplerian!) but should be sufficient 217 * for either small time shifts or coarse accuracy. 218 * </p> 219 * @param dt time shift in seconds 220 * @return a new state, shifted with respect to the instance (which is immutable) 221 */ 222 public AbsolutePVCoordinates shiftedBy(final double dt) { 223 final TimeStampedPVCoordinates spv = super.shiftedBy(dt); 224 return new AbsolutePVCoordinates(frame, spv); 225 } 226 227 /** Get a time-shifted state. 228 * <p> 229 * The state can be slightly shifted to close dates. This shift is based on 230 * a simple Taylor expansion. It is <em>not</em> intended as a replacement for 231 * proper orbit propagation (it is not even Keplerian!) but should be sufficient 232 * for either small time shifts or coarse accuracy. 233 * </p> 234 * @param dt time shift in seconds 235 * @return a new state, shifted with respect to the instance (which is immutable) 236 * @since 13.0 237 */ 238 public AbsolutePVCoordinates shiftedBy(final TimeOffset dt) { 239 final TimeStampedPVCoordinates spv = super.shiftedBy(dt); 240 return new AbsolutePVCoordinates(frame, spv); 241 } 242 243 /** Create a local provider using simply Taylor expansion through {@link #shiftedBy(double)}. 244 * <p> 245 * The time evolution is based on a simple Taylor expansion. It is <em>not</em> intended as a 246 * replacement for proper orbit propagation (it is not even Keplerian!) but should be sufficient 247 * for either small time shifts or coarse accuracy. 248 * </p> 249 * @return provider based on Taylor expansion, for small time shifts around instance date 250 */ 251 public PVCoordinatesProvider toTaylorProvider() { 252 return new PVCoordinatesProvider() { 253 /** {@inheritDoc} */ 254 public Vector3D getPosition(final AbsoluteDate d, final Frame f) { 255 final TimeStampedPVCoordinates shifted = shiftedBy(d.durationFrom(getDate())); 256 final StaticTransform transform = frame.getStaticTransformTo(f, d); 257 return transform.transformPosition(shifted.getPosition()); 258 } 259 /** {@inheritDoc} */ 260 public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate d, final Frame f) { 261 final TimeStampedPVCoordinates shifted = shiftedBy(d.durationFrom(getDate())); 262 final Transform transform = frame.getTransformTo(f, d); 263 return transform.transformPVCoordinates(shifted); 264 } 265 }; 266 } 267 268 /** Get the frame in which the coordinates are defined. 269 * @return frame in which the coordinates are defined 270 */ 271 public Frame getFrame() { 272 return frame; 273 } 274 275 /** Get the TimeStampedPVCoordinates. 276 * @return TimeStampedPVCoordinates 277 */ 278 public TimeStampedPVCoordinates getPVCoordinates() { 279 return this; 280 } 281 282 /** Get the position in a specified frame. 283 * @param outputFrame frame in which the position coordinates shall be computed 284 * @return position 285 * @see #getPVCoordinates(Frame) 286 * @since 12.0 287 */ 288 public Vector3D getPosition(final Frame outputFrame) { 289 // If output frame requested is the same as definition frame, 290 // Position vector is returned directly 291 if (outputFrame == frame) { 292 return getPosition(); 293 } 294 295 // Else, position vector is transformed to output frame 296 final StaticTransform t = frame.getStaticTransformTo(outputFrame, getDate()); 297 return t.transformPosition(getPosition()); 298 } 299 300 /** Get the TimeStampedPVCoordinates in a specified frame. 301 * @param outputFrame frame in which the position/velocity coordinates shall be computed 302 * @return TimeStampedPVCoordinates 303 * @exception OrekitException if transformation between frames cannot be computed 304 * @see #getPVCoordinates() 305 */ 306 public TimeStampedPVCoordinates getPVCoordinates(final Frame outputFrame) { 307 // If output frame requested is the same as definition frame, 308 // PV coordinates are returned directly 309 if (outputFrame == frame) { 310 return getPVCoordinates(); 311 } 312 313 // Else, PV coordinates are transformed to output frame 314 final Transform t = frame.getTransformTo(outputFrame, getDate()); 315 return t.transformPVCoordinates(getPVCoordinates()); 316 } 317 318 @Override 319 public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate otherDate, final Frame outputFrame) { 320 return shiftedBy(otherDate.durationFrom(getDate())).getPVCoordinates(outputFrame); 321 } 322 323 } 324 325 326