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.gnss.metric.messages.ssr;
18
19 import org.junit.jupiter.api.Assertions;
20 import org.junit.jupiter.api.Test;
21 import org.orekit.data.DataContext;
22 import org.orekit.errors.OrekitException;
23 import org.orekit.errors.OrekitMessages;
24 import org.orekit.gnss.SatelliteSystem;
25 import org.orekit.gnss.metric.messages.ssr.igm.SsrIgm06;
26 import org.orekit.gnss.metric.messages.ssr.igm.SsrIgm06Data;
27 import org.orekit.gnss.metric.parser.ByteArrayEncodedMessage;
28 import org.orekit.gnss.metric.parser.EncodedMessage;
29 import org.orekit.gnss.metric.parser.IgsSsrMessagesParser;
30 import org.orekit.propagation.analytical.gnss.data.GNSSConstants;
31
32 import java.util.ArrayList;
33
34 public class SsrIgm06Test {
35
36 private double eps = 1.0e-13;
37
38 @Test
39 public void testPerfectValueSBAS() {
40
41 final String m = "010000100100" + // RTCM Message number: 1060
42 "001" + // IGS SSR version
43 "01111110" + // IGS Message number: 126 (SBAS)
44 "01111110011000111111" + // Epoch Time 1s
45 "0101" + // SSR Update Interval
46 "0" + // Multiple Message Indicator
47 "0111" + // IOD SSR
48 "0000111101101111" + // SSR Provider ID
49 "0001" + // SSR Solution ID
50 "0" + // Dispersive Bias Consistency Indicator
51 "0" + // MW Consistency Indicator
52 "000001" + // No. of Satellites: 1
53 "000001" + // Satellite ID
54 "00001" + // No. of Biases Processed
55 "001100010" + // Yaw Angle
56 "01001010"+ // Yaw Rate
57 "00001" + // GNSS Signal and Tracking Mode Identifier
58 "1" + // Signal Integer Indicator
59 "10" + // Signals Wide-Lane Integer Indicator
60 "0000" + // Signal Discontinuity Counter
61 "001110101110100110100000"; // Phase Bias
62
63 final EncodedMessage message = new ByteArrayEncodedMessage(byteArrayFromBinary(m));
64 message.start();
65
66 ArrayList<Integer> messages = new ArrayList<>();
67 messages.add(126);
68
69 final SsrIgm06 igm06 = (SsrIgm06) new IgsSsrMessagesParser(messages, DataContext.getDefault().getTimeScales()).
70 parse(message, false);
71
72 // Verify size
73 Assertions.assertEquals(1, igm06.getData().size());
74 Assertions.assertEquals(SatelliteSystem.SBAS, igm06.getSatelliteSystem());
75
76 // Verify header
77 Assertions.assertEquals(126, igm06.getTypeCode());
78 Assertions.assertEquals(517695.0, igm06.getHeader().getSsrEpoch1s(), eps);
79 Assertions.assertEquals(30.0, igm06.getHeader().getSsrUpdateInterval(), eps);
80 Assertions.assertEquals(0, igm06.getHeader().getSsrMultipleMessageIndicator());
81 Assertions.assertEquals(7, igm06.getHeader().getIodSsr());
82 Assertions.assertEquals(3951, igm06.getHeader().getSsrProviderId());
83 Assertions.assertEquals(1, igm06.getHeader().getSsrSolutionId());
84 Assertions.assertEquals(1, igm06.getHeader().getNumberOfSatellites());
85 Assertions.assertFalse(igm06.getHeader().isMelbourneWubbenaConsistencyMaintained());
86 Assertions.assertFalse(igm06.getHeader().isConsistencyMaintained());
87
88 // Verify data for satellite S120
89 final SsrIgm06Data s120 = igm06.getSsrIgm06Data().get("S120").get(0);
90 Assertions.assertEquals(120, s120.getSatelliteID());
91 Assertions.assertEquals(1, s120.getNumberOfBiasesProcessed());
92 Assertions.assertEquals(1, s120.getPhaseBiases().size());
93 Assertions.assertEquals(98.0, s120.getYawAngle() * 256.0 / GNSSConstants.GNSS_PI, eps);
94 Assertions.assertEquals(74.0, s120.getYawRate() * 8192.0 / GNSSConstants.GNSS_PI, eps);
95 Assertions.assertEquals(1, s120.getPhaseBias(1).getSignalID(), eps);
96 Assertions.assertEquals(2, s120.getPhaseBias(1).getSignalWideLaneIntegerIndicator());
97 Assertions.assertEquals(0, s120.getPhaseBias(1).getDiscontinuityCounter());
98 Assertions.assertEquals(24.1306, s120.getPhaseBias(1).getPhaseBias(), eps);
99 Assertions.assertTrue(s120.getPhaseBias(1).isSignalInteger());
100
101 }
102
103 @Test
104 public void testPerfectValueGalileo() {
105
106 final String m = "010000100100" + // RTCM Message number: 1060
107 "001" + // IGS SSR version
108 "01000010" + // IGS Message number: 66 (Galileo)
109 "01111110011000111111" + // Epoch Time 1s
110 "1100" + // SSR Update Interval
111 "0" + // Multiple Message Indicator
112 "0111" + // IOD SSR
113 "0000111101101111" + // SSR Provider ID
114 "0001" + // SSR Solution ID
115 "1" + // Dispersive Bias Consistency Indicator
116 "1" + // MW Consistency Indicator
117 "000001" + // No. of Satellites: 1
118 "000001" + // Satellite ID
119 "00001" + // No. of Biases Processed
120 "001100010" + // Yaw Angle
121 "01001010"+ // Yaw Rate
122 "00001" + // GNSS Signal and Tracking Mode Identifier
123 "0" + // Signal Integer Indicator
124 "10" + // Signals Wide-Lane Integer Indicator
125 "0000" + // Signal Discontinuity Counter
126 "001110101110100110100000"; // Phase Bias
127
128 final EncodedMessage message = new ByteArrayEncodedMessage(byteArrayFromBinary(m));
129 message.start();
130
131 ArrayList<Integer> messages = new ArrayList<>();
132 messages.add(66);
133
134 final SsrIgm06 igm06 = (SsrIgm06) new IgsSsrMessagesParser(messages, DataContext.getDefault().getTimeScales()).
135 parse(message, false);
136
137 // Verify size
138 Assertions.assertEquals(1, igm06.getData().size());
139 Assertions.assertEquals(SatelliteSystem.GALILEO, igm06.getSatelliteSystem());
140
141 // Verify header
142 Assertions.assertEquals(66, igm06.getTypeCode());
143 Assertions.assertEquals(517695.0, igm06.getHeader().getSsrEpoch1s(), eps);
144 Assertions.assertEquals(1800.0, igm06.getHeader().getSsrUpdateInterval(), eps);
145 Assertions.assertEquals(0, igm06.getHeader().getSsrMultipleMessageIndicator());
146 Assertions.assertEquals(7, igm06.getHeader().getIodSsr());
147 Assertions.assertEquals(3951, igm06.getHeader().getSsrProviderId());
148 Assertions.assertEquals(1, igm06.getHeader().getSsrSolutionId());
149 Assertions.assertEquals(1, igm06.getHeader().getNumberOfSatellites());
150 Assertions.assertTrue(igm06.getHeader().isMelbourneWubbenaConsistencyMaintained());
151 Assertions.assertTrue(igm06.getHeader().isConsistencyMaintained());
152
153 // Verify data for satellite E01
154 final SsrIgm06Data e01 = igm06.getSsrIgm06Data().get("E01").get(0);
155 Assertions.assertEquals(1, e01.getSatelliteID());
156 Assertions.assertEquals(1, e01.getNumberOfBiasesProcessed());
157 Assertions.assertEquals(1, e01.getPhaseBiases().size());
158 Assertions.assertEquals(98.0, e01.getYawAngle() * 256.0 / GNSSConstants.GNSS_PI, eps);
159 Assertions.assertEquals(74.0, e01.getYawRate() * 8192.0 / GNSSConstants.GNSS_PI, eps);
160 Assertions.assertEquals(1, e01.getPhaseBias(1).getSignalID(), eps);
161 Assertions.assertEquals(2, e01.getPhaseBias(1).getSignalWideLaneIntegerIndicator());
162 Assertions.assertEquals(0, e01.getPhaseBias(1).getDiscontinuityCounter());
163 Assertions.assertEquals(24.1306, e01.getPhaseBias(1).getPhaseBias(), eps);
164 Assertions.assertFalse(e01.getPhaseBias(1).isSignalInteger());
165
166 }
167
168 @Test
169 public void testNullMessage() {
170
171 final String m = "010000100100" + // RTCM Message number: 1060
172 "001" + // IGS SSR version
173 "01101001" + // IGS Message number: 126 (SBAS)
174 "01111110011000111111" + // Epoch Time 1s
175 "0101" + // SSR Update Interval
176 "0" + // Multiple Message Indicator
177 "0111" + // IOD SSR
178 "0000111101101111" + // SSR Provider ID
179 "0001" + // SSR Solution ID
180 "0" + // Dispersive Bias Consistency Indicator
181 "0" + // MW Consistency Indicator
182 "000001" + // No. of Satellites: 1
183 "000001" + // Satellite ID
184 "00001" + // No. of Biases Processed
185 "001100010" + // Yaw Angle
186 "01001010"+ // Yaw Rate
187 "00001" + // GNSS Signal and Tracking Mode Identifier
188 "1" + // Signal Integer Indicator
189 "10" + // Signals Wide-Lane Integer Indicator
190 "0000" + // Signal Discontinuity Counter
191 "001110101110100110100000"; // Phase Bias
192
193
194 final EncodedMessage message = new ByteArrayEncodedMessage(byteArrayFromBinary(m));
195 message.start();
196
197 ArrayList<Integer> messages = new ArrayList<>();
198 messages.add(9999999);
199
200 final SsrIgm06 igm06 = (SsrIgm06) new IgsSsrMessagesParser(messages, DataContext.getDefault().getTimeScales()).
201 parse(message, false);
202
203 Assertions.assertNull(igm06);
204 }
205
206 @Test
207 public void testEmptyMessage() {
208 try {
209 final byte[] array = new byte[0];
210 final EncodedMessage emptyMessage = new ByteArrayEncodedMessage(array);
211 new IgsSsrMessagesParser(new ArrayList<>(), DataContext.getDefault().getTimeScales()).
212 parse(emptyMessage, false);
213 Assertions.fail("an exception should have been thrown");
214 } catch (OrekitException oe) {
215 Assertions.assertEquals(OrekitMessages.END_OF_ENCODED_MESSAGE, oe.getSpecifier());
216 }
217
218 }
219
220 private byte[] byteArrayFromBinary(String radix2Value) {
221 final byte[] array = new byte[radix2Value.length() / 8];
222 for (int i = 0; i < array.length; ++i) {
223 for (int j = 0; j < 8; ++j) {
224 if (radix2Value.charAt(8 * i + j) != '0') {
225 array[i] |= 0x1 << (7 - j);
226 }
227 }
228 }
229 return array;
230 }
231
232 }