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.rtcm;
18
19 import org.hipparchus.ode.nonstiff.ClassicalRungeKuttaIntegrator;
20 import org.junit.jupiter.api.Assertions;
21 import org.junit.jupiter.api.BeforeEach;
22 import org.junit.jupiter.api.Test;
23 import org.orekit.Utils;
24 import org.orekit.data.DataContext;
25 import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1020;
26 import org.orekit.gnss.metric.messages.rtcm.ephemeris.Rtcm1020Data;
27 import org.orekit.gnss.metric.parser.ByteArrayEncodedMessage;
28 import org.orekit.gnss.metric.parser.EncodedMessage;
29 import org.orekit.gnss.metric.parser.RtcmDataField;
30 import org.orekit.gnss.metric.parser.RtcmMessagesParser;
31 import org.orekit.propagation.analytical.gnss.data.GLONASSNavigationMessage;
32 import org.orekit.propagation.numerical.GLONASSNumericalPropagator;
33 import org.orekit.propagation.numerical.GLONASSNumericalPropagatorBuilder;
34 import org.orekit.time.GLONASSDate;
35
36 import java.util.ArrayList;
37
38 public class Rtcm1020Test {
39
40 private double eps = 1.0e-16;
41
42 @BeforeEach
43 public void setUp() {
44 Utils.setDataRoot("gnss");
45 }
46
47 @Test
48 public void testParseMessage() {
49
50 final String m = "001111111100" + // Message number: 1020
51 "001100" + // Satellite ID
52 "10001" + // Channel number
53 "1" + // Cn word
54 "0" + // Health availability indicator
55 "01" + // Word P1
56 "001100011011" + // tk
57 "0" + // Bn word
58 "1" + // P2 flag
59 "0011101" + // tb
60 "000000111110000011111010" + // xn first derivative
61 "000011111110000011111010010" + // xn
62 "01101" + // xn second derivative
63 "100000111110000011111010" + // yn first derivative
64 "100011111110000011111010010" + // yn
65 "11101" + // yn second derivative
66 "110000111110000011111010" + // zn first derivative
67 "101011111110000011111010010" + // zn
68 "01101" + // zn second derivative
69 "0" + // P3 flag
70 "00111100101" + // GLONASS γn (tb)
71 "11" + // Time Operation Mode
72 "0" + // ln (third string)
73 "0011101011001110101011" + // τn (tb)
74 "01110" + // Δτn
75 "01110" + // En
76 "1" + // P4 Flag
77 "1110" + // Ft
78 "10011011010" + // Nt
79 "01" + // GLONASS-M Flag
80 "1" + // Availability of additional data
81 "10011011010" + // NA
82 "00001100001111100011110011110000" + // τc
83 "00111" + // N4
84 "0011011100111101010111" + // τGPS
85 "0" + // ln (fifth string)
86 "0000000"; // Reserved
87
88 final EncodedMessage message = new ByteArrayEncodedMessage(byteArrayFromBinary(m));
89 message.start();
90
91 ArrayList<Integer> messages = new ArrayList<>();
92 messages.add(1020);
93
94 final Rtcm1020 rtcm1020 = (Rtcm1020) new RtcmMessagesParser(messages, DataContext.getDefault().getTimeScales()).
95 parse(message, false);
96 final Rtcm1020Data ephemerisData = rtcm1020.getEphemerisData();
97 final GLONASSNavigationMessage glonassMessage = ephemerisData.getGlonassNavigationMessage();
98
99 // Verify propagator initialization
100 final GLONASSNumericalPropagator propagator = new GLONASSNumericalPropagatorBuilder(new ClassicalRungeKuttaIntegrator(60.0), glonassMessage, true).build();
101 Assertions.assertNotNull(propagator);
102 Assertions.assertEquals(0.0, glonassMessage.getDate().
103 durationFrom(new GLONASSDate(ephemerisData.getNt(), ephemerisData.getN4(), glonassMessage.getTime()).getDate()), eps);
104
105 Assertions.assertEquals(12, glonassMessage.getPRN());
106 Assertions.assertEquals(10, glonassMessage.getFrequencyNumber());
107 Assertions.assertFalse(ephemerisData.isHealthAvailable());
108 Assertions.assertEquals(1800, ephemerisData.getP1());
109 Assertions.assertEquals(22410.0, ephemerisData.getTk(), eps);
110 Assertions.assertEquals(0, ephemerisData.getBN());
111 Assertions.assertEquals(1, ephemerisData.getP2());
112 Assertions.assertEquals(26100.0, glonassMessage.getTime(), eps);
113 Assertions.assertEquals(242.42592, glonassMessage.getXDot(), 2.0e-6);
114 Assertions.assertEquals(1.21071935E-5, glonassMessage.getXDotDot(), 2.0e-6);
115 Assertions.assertEquals(4064977.5390625, glonassMessage.getX(), eps);
116 Assertions.assertEquals(-242.42592, glonassMessage.getYDot(), 2.0e-6);
117 Assertions.assertEquals(-1.21071935E-5, glonassMessage.getYDotDot(), 2.0e-6);
118 Assertions.assertEquals(-4064977.5390625, glonassMessage.getY(), eps);
119 Assertions.assertEquals(-4242.426, glonassMessage.getZDot(), 2.5e-4);
120 Assertions.assertEquals(1.21071935E-5, glonassMessage.getZDotDot(), 2.0e-6);
121 Assertions.assertEquals(-1.22569775390625E7, glonassMessage.getZ(), eps);
122 Assertions.assertEquals(4, ephemerisData.getP3());
123 Assertions.assertEquals(3, ephemerisData.getP());
124 Assertions.assertEquals(0, ephemerisData.getLNThirdString());
125 Assertions.assertEquals(14, ephemerisData.getEn());
126 Assertions.assertEquals(1.30385160446367E-8, ephemerisData.getDeltaTN(), eps);
127 Assertions.assertEquals(1, ephemerisData.getP4());
128 Assertions.assertEquals(14, ephemerisData.getFT());
129 Assertions.assertEquals(1, ephemerisData.getM());
130 Assertions.assertTrue(ephemerisData.areAdditionalDataAvailable());
131 Assertions.assertEquals(1242, ephemerisData.getNA());
132 Assertions.assertEquals(0.095649354159832, ephemerisData.getTauC(), eps);
133 Assertions.assertEquals(4.214453510940075E-4, ephemerisData.getTauGps(), eps);
134 Assertions.assertEquals(0, ephemerisData.getLNFifthString());
135
136 }
137
138 @Test
139 public void testNullMessage() {
140
141 final String m = "001111111100" + // Message number: 1020
142 "001100" + // Satellite ID
143 "10001" + // Channel number
144 "1" + // Cn word
145 "0" + // Health availability indicator
146 "01" + // Word P1
147 "001100011011" + // tk
148 "0" + // Bn word
149 "1" + // P2 flag
150 "0011101" + // tb
151 "000000111110000011111010" + // xn first derivative
152 "000011111110000011111010010" + // xn
153 "01101" + // xn second derivative
154 "100000111110000011111010" + // yn first derivative
155 "100011111110000011111010010" + // yn
156 "11101" + // yn second derivative
157 "110000111110000011111010" + // zn first derivative
158 "101011111110000011111010010" + // zn
159 "01101" + // zn second derivative
160 "0" + // P3 flag
161 "00111100101" + // GLONASS γn (tb)
162 "11" + // Time Operation Mode
163 "0" + // ln (third string)
164 "0011101011001110101011" + // τn (tb)
165 "01110" + // Δτn
166 "01110" + // En
167 "1" + // P4 Flag
168 "1110" + // Ft
169 "10011011010" + // Nt
170 "01" + // GLONASS-M Flag
171 "1" + // Availability of additional data
172 "10011011010" + // NA
173 "00001100001111100011110011110000" + // τc
174 "00111" + // N4
175 "0011011100111101010111" + // τGPS
176 "0" + // ln (fifth string)
177 "0000000"; // Reserved
178
179 final EncodedMessage message = new ByteArrayEncodedMessage(byteArrayFromBinary(m));
180 message.start();
181
182 ArrayList<Integer> messages = new ArrayList<>();
183 messages.add(9999999);
184
185 final Rtcm1020 rtcm1020 = (Rtcm1020) new RtcmMessagesParser(messages, DataContext.getDefault().getTimeScales()).
186 parse(message, false);
187
188 Assertions.assertNull(rtcm1020);
189 }
190
191 @Test
192 public void testAdditionalDataFields() {
193 String m = "11111111111111111";
194 EncodedMessage message = new ByteArrayEncodedMessage(byteArrayFromBinary(m));
195 Assertions.assertTrue(RtcmDataField.DF105.booleanValue(message));
196 m = "11111111111111111";
197 message = new ByteArrayEncodedMessage(byteArrayFromBinary(m));
198 Assertions.assertEquals(5, RtcmDataField.DF120.intValue(message));
199 m = "00000000000000000";
200 message = new ByteArrayEncodedMessage(byteArrayFromBinary(m));
201 Assertions.assertFalse(RtcmDataField.DF131.booleanValue(message));
202 }
203
204 private byte[] byteArrayFromBinary(String radix2Value) {
205 final byte[] array = new byte[radix2Value.length() / 8];
206 for (int i = 0; i < array.length; ++i) {
207 for (int j = 0; j < 8; ++j) {
208 if (radix2Value.charAt(8 * i + j) != '0') {
209 array[i] |= 0x1 << (7 - j);
210 }
211 }
212 }
213 return array;
214 }
215
216 }