1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.gnss.attitude;
18
19 import org.hipparchus.Field;
20 import org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.util.FastMath;
22 import org.orekit.frames.Frame;
23 import org.orekit.time.AbsoluteDate;
24 import org.orekit.utils.ExtendedPositionProvider;
25 import org.orekit.utils.TimeStampedAngularCoordinates;
26 import org.orekit.utils.TimeStampedFieldAngularCoordinates;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public class GPSBlockIIF extends AbstractGNSSAttitudeProvider {
42
43
44 public static final double DEFAULT_YAW_RATE = FastMath.toRadians(0.11);
45
46
47 public static final double DEFAULT_YAW_BIAS = FastMath.toRadians(-0.7);
48
49
50 private static final double NIGHT_TURN_LIMIT = FastMath.toRadians(180.0 - 13.25);
51
52
53 private static final double END_MARGIN = 1800.0;
54
55
56 private final double yawRate;
57
58
59 private final double yawBias;
60
61
62
63
64
65
66
67
68
69 public GPSBlockIIF(final double yawRate, final double yawBias,
70 final AbsoluteDate validityStart, final AbsoluteDate validityEnd,
71 final ExtendedPositionProvider sun, final Frame inertialFrame) {
72 super(validityStart, validityEnd, sun, inertialFrame);
73 this.yawRate = yawRate;
74 this.yawBias = yawBias;
75 }
76
77
78 @Override
79 protected TimeStampedAngularCoordinates correctedYaw(final GNSSAttitudeContext context) {
80
81
82 final double aNoon = FastMath.atan(context.getMuRate() / yawRate);
83 final double aNight = NIGHT_TURN_LIMIT;
84 final double cNoon = FastMath.cos(aNoon);
85 final double cNight = FastMath.cos(aNight);
86
87 if (context.setUpTurnRegion(cNight, cNoon)) {
88
89 final double absBeta = FastMath.abs(context.beta(context.getDate()));
90 context.setHalfSpan(context.inSunSide() ?
91 absBeta * FastMath.sqrt(aNoon / absBeta - 1.0) :
92 context.inOrbitPlaneAbsoluteAngle(aNight - FastMath.PI),
93 END_MARGIN);
94 if (context.inTurnTimeRange()) {
95
96
97 final double beta = context.getSecuredBeta();
98 final double phiStart = context.getYawStart(beta);
99 final double dtStart = context.timeSinceTurnStart();
100 final double phiDot;
101 final double linearPhi;
102 if (context.inSunSide()) {
103
104 if (beta > yawBias && beta < 0) {
105
106
107 phiDot = FastMath.copySign(yawRate, beta);
108 linearPhi = phiStart + phiDot * dtStart;
109 } else {
110
111 phiDot = -FastMath.copySign(yawRate, beta);
112 linearPhi = phiStart + phiDot * dtStart;
113 }
114 } else {
115
116 phiDot = context.yawRate(beta);
117 linearPhi = phiStart + phiDot * dtStart;
118 }
119
120 if (context.linearModelStillActive(linearPhi, phiDot)) {
121
122 return context.turnCorrectedAttitude(linearPhi, phiDot);
123 }
124
125
126 }
127
128 }
129
130
131 return context.nominalYaw(context.getDate());
132
133 }
134
135
136 @Override
137 protected <T extends CalculusFieldElement<T>> TimeStampedFieldAngularCoordinates<T> correctedYaw(final GNSSFieldAttitudeContext<T> context) {
138
139 final Field<T> field = context.getDate().getField();
140
141
142 final T aNoon = FastMath.atan(context.getMuRate().divide(yawRate));
143 final T aNight = field.getZero().newInstance(NIGHT_TURN_LIMIT);
144 final double cNoon = FastMath.cos(aNoon.getReal());
145 final double cNight = FastMath.cos(aNight.getReal());
146
147 if (context.setUpTurnRegion(cNight, cNoon)) {
148
149 final T absBeta = FastMath.abs(context.beta(context.getDate()));
150 context.setHalfSpan(context.inSunSide() ?
151 absBeta.multiply(FastMath.sqrt(aNoon.divide(absBeta).subtract(1.0))) :
152 context.inOrbitPlaneAbsoluteAngle(aNight.subtract(aNoon.getPi())),
153 END_MARGIN);
154 if (context.inTurnTimeRange()) {
155
156
157 final T beta = context.getSecuredBeta();
158 final T phiStart = context.getYawStart(beta);
159 final T dtStart = context.timeSinceTurnStart();
160 final T phiDot;
161 final T linearPhi;
162 if (context.inSunSide()) {
163
164 if (beta.getReal() > yawBias && beta.getReal() < 0) {
165
166
167 phiDot = field.getZero().newInstance(FastMath.copySign(yawRate, beta.getReal()));
168 linearPhi = phiStart.add(phiDot.multiply(dtStart));
169 } else {
170
171 phiDot = field.getZero().newInstance(-FastMath.copySign(yawRate, beta.getReal()));
172 linearPhi = phiStart.add(phiDot.multiply(dtStart));
173 }
174 } else {
175
176 phiDot = context.yawRate(beta);
177 linearPhi = phiStart.add(phiDot.multiply(dtStart));
178 }
179
180 if (context.linearModelStillActive(linearPhi, phiDot)) {
181
182 return context.turnCorrectedAttitude(linearPhi, phiDot);
183 }
184
185 }
186
187 }
188
189
190 return context.nominalYaw(context.getDate());
191
192 }
193
194 }