1   /* Copyright 2022-2025 Luc Maisonobe
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.files.ccsds.ndm.adm;
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.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.hipparchus.util.FastMath;
24  import org.hipparchus.util.MathUtils;
25  import org.orekit.attitudes.Attitude;
26  import org.orekit.utils.TimeStampedAngularCoordinates;
27  
28  /** Utility to extract spin data.
29   * <p>
30   * In CCSDS ADM, spin axis is forced to Z. It is not the instantaneous rotation
31   * rate as it also moves.
32   * </p>
33   * @author Luc Maisonobe
34   * @since 12.0
35   */
36  class SpinFinder {
37  
38      /** Spin axis. */
39      private final Vector3D spin;
40  
41      /** Right ascension of spin axis (rad). */
42      private final double spinAlpha;
43  
44      /** declination of spin axis (rad). */
45      private final double spinDelta;
46  
47      /** Spin angle. */
48      private final double spinAngle;
49  
50      /** Build from attitude rotation.
51       * @param attitude angular coordinates, using {@link Attitude Attitude} convention
52       * (i.e. from inertial frame to spacecraft frame)
53       */
54      SpinFinder(final TimeStampedAngularCoordinates attitude) {
55          // spin axis is forced to Z (but it is not the instantaneous rotation rate as it also moves)
56          spin      = attitude.getRotation().applyInverseTo(Vector3D.PLUS_K);
57          spinAlpha = spin.getAlpha();
58          spinDelta = spin.getDelta();
59          final Rotation alignSpin   = new Rotation(RotationOrder.ZXZ, RotationConvention.FRAME_TRANSFORM,
60                                                    MathUtils.SEMI_PI + spinAlpha,
61                                                    MathUtils.SEMI_PI - spinDelta,
62                                                    0.0);
63          final Rotation phasing     = attitude.getRotation().applyTo(alignSpin.revert());
64          spinAngle = FastMath.copySign(phasing.getAngle(),
65                                        phasing.getAxis(RotationConvention.FRAME_TRANSFORM).getZ());
66  
67      }
68  
69      /** Get the spin axis in inertial frame.
70       * @return spin axis in inertial frame
71       */
72      public Vector3D getSpin() {
73          return spin;
74      }
75  
76      /** Get the declination of spin axis.
77       * @return declination of spin axis (rad)
78       */
79      public double getSpinDelta() {
80          return spinDelta;
81      }
82  
83      /** Get the right ascension of spin axis.
84       * @return right ascension of spin axis (rad)
85       */
86      public double getSpinAlpha() {
87          return spinAlpha;
88      }
89  
90      /** Get the spin angle.
91       * @return spin angle (rad)
92       */
93      public double getSpinAngle() {
94          return spinAngle;
95      }
96  
97  }