1 /* Copyright 2002-2015 CS Systèmes d'Information 2 * Licensed to CS Systèmes d'Information (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.attitudes; 18 19 import org.apache.commons.math3.geometry.euclidean.threed.Rotation; 20 import org.apache.commons.math3.geometry.euclidean.threed.RotationOrder; 21 import org.orekit.errors.OrekitException; 22 import org.orekit.errors.OrekitMessages; 23 import org.orekit.frames.Frame; 24 import org.orekit.frames.LOFType; 25 import org.orekit.frames.Transform; 26 import org.orekit.time.AbsoluteDate; 27 import org.orekit.utils.PVCoordinates; 28 import org.orekit.utils.PVCoordinatesProvider; 29 30 31 /** 32 * Attitude law defined by fixed Roll, Pitch and Yaw angles (in any order) 33 * with respect to a local orbital frame. 34 35 * <p> 36 * The attitude provider is defined as a rotation offset from some local orbital frame. 37 * @author Véronique Pommier-Maurussane 38 */ 39 public class LofOffset implements AttitudeProvider { 40 41 /** Serializable UID. */ 42 private static final long serialVersionUID = -713570668596014285L; 43 44 /** Type of Local Orbital Frame. */ 45 private LOFType type; 46 47 /** Rotation from local orbital frame. */ 48 private final Rotation offset; 49 50 /** Inertial frame with respect to which orbit should be computed. */ 51 private final Frame inertialFrame; 52 53 /** Create a LOF-aligned attitude. 54 * <p> 55 * Calling this constructor is equivalent to call 56 * {@code LofOffset(inertialFrame, LOFType, RotationOrder.XYZ, 0, 0, 0)} 57 * </p> 58 * @param inertialFrame inertial frame with respect to which orbit should be computed 59 * @param type type of Local Orbital Frame 60 * @exception OrekitException if inertialFrame is not a pseudo-inertial frame 61 */ 62 public LofOffset(final Frame inertialFrame, final LOFType type) throws OrekitException { 63 this(inertialFrame, type, RotationOrder.XYZ, 0, 0, 0); 64 } 65 66 /** Creates new instance. 67 * <p> 68 * An important thing to note is that the rotation order and angles signs used here 69 * are compliant with an <em>attitude</em> definition, i.e. they correspond to 70 * a frame that rotate in a field of fixed vectors. The underlying definitions used 71 * in commons-math {@link org.apache.commons.math3.geometry.euclidean.threed.Rotation#Rotation(RotationOrder, 72 * double, double, double) Rotation(RotationOrder, double, double, double)} use 73 * <em>reversed</em> definition, i.e. they correspond to a vectors field rotating 74 * with respect to a fixed frame. So to retrieve the angles provided here from the 75 * commons-math underlying rotation, one has to <em>revert</em> the rotation, as in 76 * the following code snippet: 77 * </p> 78 * <pre> 79 * LofOffset law = new LofOffset(inertial, lofType, order, alpha1, alpha2, alpha3); 80 * Rotation offsetAtt = law.getAttitude(orbit).getRotation(); 81 * Rotation alignedAtt = new LofOffset(inertial, lofType).getAttitude(orbit).getRotation(); 82 * Rotation offsetProper = offsetAtt.applyTo(alignedAtt.revert()); 83 * 84 * // note the call to revert in the following statement 85 * double[] angles = offsetProper.revert().getAngles(order); 86 * 87 * System.out.println(alpha1 + " == " + angles[0]); 88 * System.out.println(alpha2 + " == " + angles[1]); 89 * System.out.println(alpha3 + " == " + angles[2]); 90 * </pre> 91 * @param inertialFrame inertial frame with respect to which orbit should be computed 92 * @param type type of Local Orbital Frame 93 * @param order order of rotations to use for (alpha1, alpha2, alpha3) composition 94 * @param alpha1 angle of the first elementary rotation 95 * @param alpha2 angle of the second elementary rotation 96 * @param alpha3 angle of the third elementary rotation 97 * @exception OrekitException if inertialFrame is not a pseudo-inertial frame 98 */ 99 public LofOffset(final Frame inertialFrame, final LOFType type, 100 final RotationOrder order, final double alpha1, 101 final double alpha2, final double alpha3) throws OrekitException { 102 this.type = type; 103 this.offset = new Rotation(order, alpha1, alpha2, alpha3).revert(); 104 if (!inertialFrame.isPseudoInertial()) { 105 throw new OrekitException(OrekitMessages.NON_PSEUDO_INERTIAL_FRAME_NOT_SUITABLE_FOR_DEFINING_ORBITS, 106 inertialFrame.getName()); 107 } 108 this.inertialFrame = inertialFrame; 109 } 110 111 112 /** {@inheritDoc} */ 113 public Attitude getAttitude(final PVCoordinatesProvider pvProv, 114 final AbsoluteDate date, final Frame frame) 115 throws OrekitException { 116 117 // construction of the local orbital frame, using PV from inertial frame 118 final PVCoordinates pv = pvProv.getPVCoordinates(date, inertialFrame); 119 final Transform inertialToLof = type.transformFromInertial(date, pv); 120 121 // take into account the specified start frame (which may not be an inertial one) 122 final Transform frameToInertial = frame.getTransformTo(inertialFrame, date); 123 final Transform frameToLof = new Transform(date, frameToInertial, inertialToLof); 124 125 // compose with offset rotation 126 return new Attitude(date, frame, 127 offset.applyTo(frameToLof.getRotation()), 128 offset.applyTo(frameToLof.getRotationRate()), 129 offset.applyTo(frameToLof.getRotationAcceleration())); 130 131 } 132 133 }