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.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.Vector3D;
22  import org.orekit.frames.Frame;
23  import org.orekit.frames.Transform;
24  import org.orekit.time.AbsoluteDate;
25  import org.orekit.time.TimeOffset;
26  import org.orekit.time.TimeShiftable;
27  import org.orekit.time.TimeStamped;
28  import org.orekit.utils.AngularCoordinates;
29  import org.orekit.utils.TimeStampedAngularCoordinates;
30  
31  
32  /** This class handles attitude definition at a given date.
33  
34   * <p>This class represents the rotation between a reference frame and
35   * the satellite frame, as well as the spin of the satellite (axis and
36   * rotation rate).</p>
37   * <p>
38   * The state can be slightly shifted to close dates. This shift is based on
39   * a linear extrapolation for attitude taking the spin rate into account.
40   * It is <em>not</em> intended as a replacement for proper attitude propagation
41   * but should be sufficient for either small time shifts or coarse accuracy.
42   * </p>
43   * <p>The instance <code>Attitude</code> is guaranteed to be immutable.</p>
44   * @see     org.orekit.orbits.Orbit
45   * @see AttitudeProvider
46   * @author V&eacute;ronique Pommier-Maurussane
47   */
48  
49  public class Attitude implements TimeStamped, TimeShiftable<Attitude> {
50  
51      /** Reference frame. */
52      private final Frame referenceFrame;
53  
54       /** Attitude and spin.  */
55      private final TimeStampedAngularCoordinates orientation;
56  
57      /** Creates a new instance.
58       * @param referenceFrame reference frame from which attitude is defined
59       * @param orientation complete orientation between reference frame and satellite frame,
60       * including rotation rate
61       */
62      public Attitude(final Frame referenceFrame, final TimeStampedAngularCoordinates orientation) {
63          this.referenceFrame = referenceFrame;
64          this.orientation    = orientation;
65      }
66  
67      /** Creates a new instance.
68       * @param date date at which attitude is defined
69       * @param referenceFrame reference frame from which attitude is defined
70       * @param orientation complete orientation between reference frame and satellite frame,
71       * including rotation rate
72       */
73      public Attitude(final AbsoluteDate date, final Frame referenceFrame,
74                      final AngularCoordinates orientation) {
75          this(referenceFrame,
76               new TimeStampedAngularCoordinates(date,
77                                                 orientation.getRotation(),
78                                                 orientation.getRotationRate(),
79                                                 orientation.getRotationAcceleration()));
80      }
81  
82      /** Creates a new instance.
83       * @param date date at which attitude is defined
84       * @param referenceFrame reference frame from which attitude is defined
85       * @param attitude rotation between reference frame and satellite frame
86       * @param spin satellite spin (axis and velocity, in <strong>satellite</strong> frame)
87       * @param acceleration satellite rotation acceleration (in <strong>satellite</strong> frame)
88       */
89      public Attitude(final AbsoluteDate date, final Frame referenceFrame,
90                      final Rotation attitude, final Vector3D spin, final Vector3D acceleration) {
91          this(referenceFrame, new TimeStampedAngularCoordinates(date, attitude, spin, acceleration));
92      }
93  
94      /** Get a time-shifted attitude.
95       * <p>
96       * The state can be slightly shifted to close dates. This shift is based on
97       * a linear extrapolation for attitude taking the spin rate into account.
98       * It is <em>not</em> intended as a replacement for proper attitude propagation
99       * but should be sufficient for either small time shifts or coarse accuracy.
100      * </p>
101      * @param dt time shift in seconds
102      * @return a new attitude, shifted with respect to the instance (which is immutable)
103      */
104     public Attitude shiftedBy(final double dt) {
105         return new Attitude(referenceFrame, orientation.shiftedBy(dt));
106     }
107 
108     /** Get a time-shifted attitude.
109      * <p>
110      * The state can be slightly shifted to close dates. This shift is based on
111      * a linear extrapolation for attitude taking the spin rate into account.
112      * It is <em>not</em> intended as a replacement for proper attitude propagation
113      * but should be sufficient for either small time shifts or coarse accuracy.
114      * </p>
115      * @param dt time shift
116      * @return a new attitude, shifted with respect to the instance (which is immutable)
117      * @since 13.0
118      */
119     @Override
120     public Attitude shiftedBy(final TimeOffset dt) {
121         return new Attitude(referenceFrame, orientation.shiftedBy(dt));
122     }
123 
124     /** Get a similar attitude with a specific reference frame.
125      * <p>
126      * If the instance reference frame is already the specified one, the instance
127      * itself is returned without any object creation. Otherwise, a new instance
128      * will be created with the specified reference frame. In this case, the
129      * required intermediate rotation and spin between the specified and the
130      * original reference frame will be inserted.
131      * </p>
132      * @param newReferenceFrame desired reference frame for attitude
133      * @return an attitude that has the same orientation and motion as the instance,
134      * but guaranteed to have the specified reference frame
135      */
136     public Attitude withReferenceFrame(final Frame newReferenceFrame) {
137 
138         if (newReferenceFrame == referenceFrame) {
139             // simple case, the instance is already compliant
140             return this;
141         }
142 
143         // we have to take an intermediate rotation into account
144         final Transform t = newReferenceFrame.getTransformTo(referenceFrame, orientation.getDate());
145         return new Attitude(orientation.getDate(), newReferenceFrame,
146                             orientation.getRotation().compose(t.getRotation(), RotationConvention.VECTOR_OPERATOR),
147                             orientation.getRotationRate().add(orientation.getRotation().applyTo(t.getRotationRate())),
148                             orientation.getRotationAcceleration().add(orientation.getRotation().applyTo(t.getRotationAcceleration())));
149 
150     }
151 
152     /** Get the date of attitude parameters.
153      * @return date of the attitude parameters
154      */
155     public AbsoluteDate getDate() {
156         return orientation.getDate();
157     }
158 
159     /** Get the reference frame.
160      * @return referenceFrame reference frame from which attitude is defined.
161      */
162     public Frame getReferenceFrame() {
163         return referenceFrame;
164     }
165 
166     /** Get the complete orientation including spin.
167      * @return complete orientation including spin
168      * @see #getRotation()
169      * @see #getSpin()
170      */
171     public TimeStampedAngularCoordinates getOrientation() {
172         return orientation;
173     }
174 
175     /** Get the attitude rotation.
176      * @return attitude satellite rotation from reference frame.
177      * @see #getOrientation()
178      * @see #getSpin()
179      */
180     public Rotation getRotation() {
181         return orientation.getRotation();
182     }
183 
184     /** Get the satellite spin.
185      * <p>The spin vector is defined in <strong>satellite</strong> frame.</p>
186      * @return spin satellite spin (axis and velocity).
187      * @see #getOrientation()
188      * @see #getRotation()
189      */
190     public Vector3D getSpin() {
191         return orientation.getRotationRate();
192     }
193 
194     /** Get the satellite rotation acceleration.
195      * <p>The rotation acceleration. vector is defined in <strong>satellite</strong> frame.</p>
196      * @return rotation acceleration
197      * @see #getOrientation()
198      * @see #getRotation()
199      */
200     public Vector3D getRotationAcceleration() {
201         return orientation.getRotationAcceleration();
202     }
203 
204 }