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