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.RealFieldElement;
21 import org.hipparchus.util.FastMath;
22 import org.orekit.frames.Frame;
23 import org.orekit.time.AbsoluteDate;
24 import org.orekit.utils.ExtendedPVCoordinatesProvider;
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 GPSBlockIIR extends AbstractGNSSAttitudeProvider {
42
43
44 public static final double DEFAULT_YAW_RATE = FastMath.toRadians(0.2);
45
46
47 private static final long serialVersionUID = 20171114L;
48
49
50 private final double END_MARGIN = 1800.0;
51
52
53 private final double yawRate;
54
55
56
57
58
59
60
61
62 public GPSBlockIIR(final double yawRate,
63 final AbsoluteDateDate">AbsoluteDate validityStart, final AbsoluteDate validityEnd,
64 final ExtendedPVCoordinatesProvider sun, final Frame inertialFrame) {
65 super(validityStart, validityEnd, sun, inertialFrame);
66 this.yawRate = yawRate;
67 }
68
69
70 @Override
71 protected TimeStampedAngularCoordinates correctedYaw(final GNSSAttitudeContext context) {
72
73
74 final double aNoon = FastMath.atan(context.getMuRate() / yawRate);
75 final double cNoon = FastMath.cos(aNoon);
76 final double cNight = -cNoon;
77
78 if (context.setUpTurnRegion(cNight, cNoon)) {
79
80 final double absBeta = FastMath.abs(context.beta(context.getDate()));
81 context.setHalfSpan(absBeta * FastMath.sqrt(aNoon / absBeta - 1.0), END_MARGIN);
82 if (context.inTurnTimeRange()) {
83
84
85 final double beta = context.getSecuredBeta();
86 final double phiStart = context.getYawStart(beta);
87 final double dtStart = context.timeSinceTurnStart();
88 final double phiDot;
89 final double linearPhi;
90
91 if (context.inSunSide()) {
92
93 phiDot = -FastMath.copySign(yawRate, beta);
94 linearPhi = phiStart + phiDot * dtStart;
95 } else {
96
97 phiDot = FastMath.copySign(yawRate, beta);
98 linearPhi = phiStart + phiDot * dtStart;
99 }
100
101 if (context.linearModelStillActive(linearPhi, phiDot)) {
102
103 return context.turnCorrectedAttitude(linearPhi, phiDot);
104 }
105
106 }
107
108 }
109
110
111 return context.nominalYaw(context.getDate());
112
113 }
114
115
116 @Override
117 protected <T extends RealFieldElement<T>> TimeStampedFieldAngularCoordinates<T> correctedYaw(final GNSSFieldAttitudeContext<T> context) {
118
119 final Field<T> field = context.getDate().getField();
120
121
122 final T aNoon = FastMath.atan(context.getMuRate().divide(yawRate));
123 final double cNoon = FastMath.cos(aNoon.getReal());
124 final double cNight = -cNoon;
125
126 if (context.setUpTurnRegion(cNight, cNoon)) {
127
128 final T absBeta = FastMath.abs(context.beta(context.getDate()));
129 context.setHalfSpan(absBeta.multiply(FastMath.sqrt(aNoon.divide(absBeta).subtract(1.0))), END_MARGIN);
130 if (context.inTurnTimeRange()) {
131
132
133 final T beta = context.getSecuredBeta();
134 final T phiStart = context.getYawStart(beta);
135 final T dtStart = context.timeSinceTurnStart();
136 final T phiDot;
137 final T linearPhi;
138
139 if (context.inSunSide()) {
140
141 phiDot = field.getZero().add(-FastMath.copySign(yawRate, beta.getReal()));
142 linearPhi = phiStart.add(phiDot.multiply(dtStart));
143 } else {
144
145 phiDot = field.getZero().add(FastMath.copySign(yawRate, beta.getReal()));
146 linearPhi = phiStart.add(phiDot.multiply(dtStart));
147 }
148
149 if (context.linearModelStillActive(linearPhi, phiDot)) {
150
151 return context.turnCorrectedAttitude(linearPhi, phiDot);
152 }
153
154 }
155
156 }
157
158
159 return context.nominalYaw(context.getDate());
160
161 }
162
163 }