1 /* Copyright 2002-2024 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.frames; 18 19 import org.hipparchus.CalculusFieldElement; 20 import org.hipparchus.Field; 21 import org.hipparchus.geometry.euclidean.threed.FieldRotation; 22 import org.hipparchus.geometry.euclidean.threed.FieldVector3D; 23 import org.hipparchus.geometry.euclidean.threed.Rotation; 24 import org.hipparchus.geometry.euclidean.threed.RotationConvention; 25 import org.hipparchus.geometry.euclidean.threed.Vector3D; 26 import org.orekit.time.AbsoluteDate; 27 import org.orekit.time.FieldAbsoluteDate; 28 import org.orekit.utils.FieldPVCoordinates; 29 import org.orekit.utils.PVCoordinates; 30 31 /** 32 * Interface for local orbital frame. 33 * 34 * @author Vincent Cucchietti 35 */ 36 public interface LOF { 37 38 /** 39 * Get the rotation from input to output {@link LOF local orbital frame}. 40 * <p> 41 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well, 42 * the full {@link #transformFromLOFInToLOFOut(LOF, LOF, FieldAbsoluteDate, FieldPVCoordinates)} method must be called and 43 * the complete rotation transform must be extracted from it. 44 * 45 * @param field field to which the elements belong 46 * @param in input commonly used local orbital frame 47 * @param out output commonly used local orbital frame 48 * @param date date of the rotation 49 * @param pv position-velocity of the spacecraft in some inertial frame 50 * @param <T> type of the field elements 51 * 52 * @return rotation from input to output local orbital frame 53 * 54 * @since 11.3 55 */ 56 static <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromLOFInToLOFOut(final Field<T> field, 57 final LOF in, final LOF out, 58 final FieldAbsoluteDate<T> date, 59 final FieldPVCoordinates<T> pv) { 60 return out.rotationFromLOF(field, in, date, pv); 61 } 62 63 /** 64 * Get the transform from input to output {@link LOF local orbital frame}. 65 * 66 * @param in input commonly used local orbital frame 67 * @param out output commonly used local orbital frame 68 * @param date date of the transform 69 * @param pv position-velocity of the spacecraft in some inertial frame 70 * @param <T> type of the field elements 71 * 72 * @return rotation from input to output local orbital frame. 73 * 74 * @since 11.3 75 */ 76 static <T extends CalculusFieldElement<T>> FieldTransform<T> transformFromLOFInToLOFOut(final LOF in, final LOF out, 77 final FieldAbsoluteDate<T> date, 78 final FieldPVCoordinates<T> pv) { 79 return out.transformFromLOF(in, date, pv); 80 } 81 82 /** 83 * Get the rotation from input to output {@link LOF local orbital frame}. 84 * <p> 85 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well, 86 * the full {@link #transformFromLOFInToLOFOut(LOF, LOF, AbsoluteDate, PVCoordinates)} method must be called and 87 * the complete rotation transform must be extracted from it. 88 * 89 * @param in input commonly used local orbital frame 90 * @param out output commonly used local orbital frame 91 * @param date date of the rotation 92 * @param pv position-velocity of the spacecraft in some inertial frame 93 * 94 * @return rotation from input to output local orbital frame. 95 * 96 * @since 11.3 97 */ 98 static Rotation rotationFromLOFInToLOFOut(final LOF in, final LOF out, final AbsoluteDate date, final PVCoordinates pv) { 99 return out.rotationFromLOF(in, date, pv); 100 } 101 102 /** 103 * Get the transform from input to output {@link LOF local orbital frame}. 104 * 105 * @param in input commonly used local orbital frame 106 * @param out output commonly used local orbital frame 107 * @param date date of the transform 108 * @param pv position-velocity of the spacecraft in some inertial frame 109 * 110 * @return rotation from input to output local orbital frame 111 * 112 * @since 11.3 113 */ 114 static Transform transformFromLOFInToLOFOut(final LOF in, final LOF out, final AbsoluteDate date, 115 final PVCoordinates pv) { 116 return out.transformFromLOF(in, date, pv); 117 } 118 119 /** 120 * Get the rotation from input {@link LOF local orbital frame} to the instance. 121 * <p> 122 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well, 123 * the full {@link #transformFromLOF(LOF, FieldAbsoluteDate, FieldPVCoordinates)} method must be called and 124 * the complete rotation transform must be extracted from it. 125 * 126 * @param field field to which the elements belong 127 * @param fromLOF input local orbital frame 128 * @param date date of the rotation 129 * @param pv position-velocity of the spacecraft in some inertial frame 130 * @param <T> type of the field elements 131 * 132 * @return rotation from input local orbital frame to the instance 133 * 134 * @since 11.3 135 */ 136 default <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromLOF(final Field<T> field, 137 final LOF fromLOF, 138 final FieldAbsoluteDate<T> date, 139 final FieldPVCoordinates<T> pv) { 140 141 // First compute the rotation from the input LOF to the pivot inertial 142 final FieldRotation<T> fromLOFToInertial = fromLOF.rotationFromInertial(field, date, pv).revert(); 143 144 // Then compute the rotation from the pivot inertial to the output LOF 145 final FieldRotation<T> inertialToThis = this.rotationFromInertial(field, date, pv); 146 147 // Output composed rotation 148 return fromLOFToInertial.compose(inertialToThis, RotationConvention.FRAME_TRANSFORM); 149 } 150 151 /** 152 * Get the rotation from input {@link LOF commonly used local orbital frame} to the instance. 153 * 154 * @param fromLOF input local orbital frame 155 * @param date date of the transform 156 * @param pv position-velocity of the spacecraft in some inertial frame 157 * @param <T> type of the field elements 158 * 159 * @return rotation from input local orbital frame to the instance 160 * 161 * @since 11.3 162 */ 163 default <T extends CalculusFieldElement<T>> FieldTransform<T> transformFromLOF(final LOF fromLOF, 164 final FieldAbsoluteDate<T> date, 165 final FieldPVCoordinates<T> pv) { 166 167 // Get transform from input local orbital frame to inertial 168 final FieldTransform<T> fromLOFToInertial = fromLOF.transformFromInertial(date, pv).getInverse(); 169 170 // Get transform from inertial to output local orbital frame 171 final FieldTransform<T> inertialToLOFOut = this.transformFromInertial(date, pv); 172 173 // Output composition of both transforms 174 return new FieldTransform<>(date, fromLOFToInertial, inertialToLOFOut); 175 } 176 177 /** 178 * Get the transform from an inertial frame defining position-velocity and the local orbital frame. 179 * 180 * @param date current date 181 * @param pv position-velocity of the spacecraft in some inertial frame 182 * @param <T> type of the fields elements 183 * 184 * @return transform from the frame where position-velocity are defined to local orbital frame 185 * 186 * @since 9.0 187 */ 188 default <T extends CalculusFieldElement<T>> FieldTransform<T> transformFromInertial(final FieldAbsoluteDate<T> date, 189 final FieldPVCoordinates<T> pv) { 190 191 // compute the translation part of the transform 192 final FieldTransform<T> translation = new FieldTransform<>(date, pv.negate()); 193 194 // compute the rotation part of the transform 195 final FieldRotation<T> r = rotationFromInertial(date.getField(), date, pv); 196 final FieldVector3D<T> p = pv.getPosition(); 197 final FieldVector3D<T> momentum = pv.getMomentum(); 198 final FieldTransform<T> rotation = new FieldTransform<>(date, r, 199 new FieldVector3D<>(p.getNormSq().reciprocal(), 200 r.applyTo(momentum))); 201 202 final FieldTransform<T> transform = new FieldTransform<>(date, translation, rotation); 203 204 // If LOF is considered pseudo-inertial, freeze transform 205 return isQuasiInertial() ? transform.freeze() : transform; 206 207 } 208 209 /** 210 * Get the rotation from inertial frame to local orbital frame. 211 * <p> 212 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well, 213 * the full {@link #transformFromInertial(FieldAbsoluteDate, FieldPVCoordinates)} method must be 214 * called and the complete rotation transform must be extracted from it. 215 * </p> 216 * 217 * @param field field to which the elements belong 218 * @param date date of the rotation 219 * @param pv position-velocity of the spacecraft in some inertial frame 220 * @param <T> type of the field elements 221 * 222 * @return rotation from inertial frame to local orbital frame 223 * 224 * @since 9.0 225 */ 226 <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(Field<T> field, FieldAbsoluteDate<T> date, 227 FieldPVCoordinates<T> pv); 228 229 /** 230 * Get the rotation from input {@link LOF local orbital frame} to the instance. 231 * <p> 232 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well, 233 * the full {@link #transformFromLOF(LOF, AbsoluteDate, PVCoordinates)} method must be called and 234 * the complete rotation transform must be extracted from it. 235 * 236 * @param fromLOF input local orbital frame 237 * @param date date of the rotation 238 * @param pv position-velocity of the spacecraft in some inertial frame 239 * 240 * @return rotation from input local orbital frame to the instance 241 * 242 * @since 11.3 243 */ 244 default Rotation rotationFromLOF(final LOF fromLOF, final AbsoluteDate date, final PVCoordinates pv) { 245 246 // First compute the rotation from the input LOF to the pivot inertial 247 final Rotation fromLOFToInertial = fromLOF.rotationFromInertial(date, pv).revert(); 248 249 // Then compute the rotation from the pivot inertial to the output LOF 250 final Rotation inertialToThis = this.rotationFromInertial(date, pv); 251 252 // Output composed rotation 253 return fromLOFToInertial.compose(inertialToThis, RotationConvention.FRAME_TRANSFORM); 254 } 255 256 /** 257 * Get the rotation from input {@link LOF local orbital frame} to the instance. 258 * 259 * @param fromLOF input local orbital frame 260 * @param date date of the transform 261 * @param pv position-velocity of the spacecraft in some inertial frame 262 * 263 * @return rotation from input local orbital frame to the instance 264 * 265 * @since 11.3 266 */ 267 default Transform transformFromLOF(final LOF fromLOF, final AbsoluteDate date, final PVCoordinates pv) { 268 269 // First compute the rotation from the input LOF to the pivot inertial 270 final Transform fromLOFToInertial = fromLOF.transformFromInertial(date, pv).getInverse(); 271 272 // Then compute the rotation from the pivot inertial to the output LOF 273 final Transform inertialToThis = this.transformFromInertial(date, pv); 274 275 // Output composed rotation 276 return new Transform(date, fromLOFToInertial, inertialToThis); 277 } 278 279 /** 280 * Get the transform from an inertial frame defining position-velocity and the local orbital frame. 281 * 282 * @param date current date 283 * @param pv position-velocity of the spacecraft in some inertial frame 284 * 285 * @return transform from the frame where position-velocity are defined to local orbital frame 286 */ 287 default Transform transformFromInertial(final AbsoluteDate date, final PVCoordinates pv) { 288 289 // compute the translation part of the transform 290 final Transform translation = new Transform(date, pv.negate()); 291 292 // compute the rotation part of the transform 293 final Rotation r = rotationFromInertial(date, pv); 294 final Vector3D p = pv.getPosition(); 295 final Vector3D momentum = pv.getMomentum(); 296 final Transform rotation = new Transform(date, r, new Vector3D(1.0 / p.getNormSq(), r.applyTo(momentum))); 297 298 final Transform transform = new Transform(date, translation, rotation); 299 300 // If LOF is considered pseudo-inertial, freeze transform 301 return isQuasiInertial() ? transform.freeze() : transform; 302 303 } 304 305 /** 306 * Get the rotation from inertial frame to local orbital frame. 307 * <p> 308 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well, 309 * the full {@link #transformFromInertial(AbsoluteDate, PVCoordinates) transformFromInertial} method must be called and 310 * the complete rotation transform must be extracted from it. 311 * 312 * @param date date of the rotation 313 * @param pv position-velocity of the spacecraft in some inertial frame 314 * 315 * @return rotation from inertial frame to local orbital frame 316 */ 317 Rotation rotationFromInertial(AbsoluteDate date, PVCoordinates pv); 318 319 /** Get flag that indicates if current local orbital frame shall be treated as pseudo-inertial. 320 * @return flag that indicates if current local orbital frame shall be treated as pseudo-inertial 321 */ 322 default boolean isQuasiInertial() { 323 return false; 324 } 325 326 /** Get name of the local orbital frame. 327 * @return name of the local orbital frame 328 */ 329 String getName(); 330 331 }