1 /* Copyright 2002-2021 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.CalculusFieldElement;
20 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
21 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22 import org.hipparchus.geometry.euclidean.threed.Rotation;
23 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
24 import org.hipparchus.geometry.euclidean.threed.Vector3D;
25 import org.orekit.frames.FieldTransform;
26 import org.orekit.frames.Frame;
27 import org.orekit.frames.Transform;
28 import org.orekit.time.AbsoluteDate;
29 import org.orekit.time.FieldAbsoluteDate;
30 import org.orekit.utils.FieldPVCoordinatesProvider;
31 import org.orekit.utils.PVCoordinatesProvider;
32
33
34 /**
35 * This class handles a spin stabilized attitude provider.
36 * <p>Spin stabilized laws are handled as wrappers for an underlying
37 * non-rotating law. This underlying law is typically an instance
38 * of {@link CelestialBodyPointed} with the pointing axis equal to
39 * the rotation axis, but can in fact be anything.</p>
40 * <p>Instances of this class are guaranteed to be immutable.</p>
41 * @author Luc Maisonobe
42 */
43 public class SpinStabilized implements AttitudeProviderModifier {
44
45 /** Underlying non-rotating attitude provider. */
46 private final AttitudeProvider nonRotatingLaw;
47
48 /** Start date of the rotation. */
49 private final AbsoluteDate start;
50
51 /** Rotation axis in satellite frame. */
52 private final Vector3D axis;
53
54 /** Spin rate in radians per seconds. */
55 private final double rate;
56
57 /** Spin vector. */
58 private final Vector3D spin;
59
60 /** Creates a new instance.
61 * @param nonRotatingLaw underlying non-rotating attitude provider
62 * @param start start date of the rotation
63 * @param axis rotation axis in satellite frame
64 * @param rate spin rate in radians per seconds
65 */
66 public SpinStabilized(final AttitudeProvider nonRotatingLaw,
67 final AbsoluteDate start,
68 final Vector3D axis, final double rate) {
69 this.nonRotatingLaw = nonRotatingLaw;
70 this.start = start;
71 this.axis = axis;
72 this.rate = rate;
73 this.spin = new Vector3D(rate / axis.getNorm(), axis);
74 }
75
76 /** {@inheritDoc} */
77 public AttitudeProvider getUnderlyingAttitudeProvider() {
78 return nonRotatingLaw;
79 }
80
81 /** {@inheritDoc} */
82 public Attitude getAttitude(final PVCoordinatesProvider pvProv,
83 final AbsoluteDate date, final Frame frame) {
84
85 // get attitude from underlying non-rotating law
86 final Attitude base = nonRotatingLaw.getAttitude(pvProv, date, frame);
87 final Transform baseTransform = new Transform(date, base.getOrientation());
88
89 // compute spin transform due to spin from reference to current date
90 final Transform spinInfluence =
91 new Transform(date,
92 new Rotation(axis,
93 rate * date.durationFrom(start),
94 RotationConvention.FRAME_TRANSFORM),
95 spin);
96
97 // combine the two transforms
98 final Transform combined = new Transform(date, baseTransform, spinInfluence);
99
100 // build the attitude
101 return new Attitude(date, frame,
102 combined.getRotation(), combined.getRotationRate(), combined.getRotationAcceleration());
103
104 }
105
106 /** {@inheritDoc} */
107 public <T extends CalculusFieldElement<T>> FieldAttitude<T> getAttitude(final FieldPVCoordinatesProvider<T> pvProv,
108 final FieldAbsoluteDate<T> date,
109 final Frame frame) {
110
111 // get attitude from underlying non-rotating law
112 final FieldAttitude<T> base = nonRotatingLaw.getAttitude(pvProv, date, frame);
113 final FieldTransform<T> baseTransform = new FieldTransform<>(date, base.getOrientation());
114
115 // compute spin transform due to spin from reference to current date
116 final FieldTransform<T> spinInfluence =
117 new FieldTransform<>(date,
118 new FieldRotation<>(new FieldVector3D<>(date.getField(), axis),
119 date.durationFrom(start).multiply(rate),
120 RotationConvention.FRAME_TRANSFORM),
121 new FieldVector3D<>(date.getField(), spin));
122
123 // combine the two transforms
124 final FieldTransform<T> combined = new FieldTransform<>(date, baseTransform, spinInfluence);
125
126 // build the attitude
127 return new FieldAttitude<>(date, frame,
128 combined.getRotation(), combined.getRotationRate(), combined.getRotationAcceleration());
129
130 }
131
132 }