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.SsrIgm01;
26  import org.orekit.gnss.metric.messages.ssr.igm.SsrIgm01Data;
27  import org.orekit.gnss.metric.parser.ByteArrayEncodedMessage;
28  import org.orekit.gnss.metric.parser.EncodedMessage;
29  import org.orekit.gnss.metric.parser.IgsSsrDataField;
30  import org.orekit.gnss.metric.parser.IgsSsrMessagesParser;
31  
32  import java.util.ArrayList;
33  
34  
35  public class SsrIgm01Test {
36  
37      private final double eps = 1.0e-13;
38  
39      @Test
40      public void testPerfectValueGPS() {
41  
42          final String m = "010000100100" +                 // RTCM Message number: 1060
43                           "001" +                          // IGS SSR version
44                           "00010101" +                     // IGS Message number: 21 (GPS)
45                           "01111110011000111111" +         // Epoch Time 1s
46                           "0010" +                         // SSR Update Interval
47                           "0" +                            // Multiple Message Indicator
48                           "0111" +                         // IOD SSR
49                           "0000111101101111" +             // SSR Provider ID
50                           "0001" +                         // SSR Solution ID
51                           "0" +                            // Global/Regional CRS Indicator
52                           "000001" +                       // No. of Satellites
53                           "001100" +                       // Satellite ID
54                           "10000100" +                     // GNSS IOD
55                           "0000101011111101111111" +       // Delta Radial
56                           "01001010111111011111" +         // Delta Along-Track
57                           "01001010111111011111" +         // Delta Cross-Track
58                           "000010101111110111111" +        // Dot Delta Radial
59                           "0100101011111101111" +          // Dot Delta Along-Track
60                           "010010101111110111100";         // Dot Delta Cross-Track
61  
62          final EncodedMessage message = new ByteArrayEncodedMessage(byteArrayFromBinary(m));
63          message.start();
64  
65          ArrayList<Integer> messages = new ArrayList<>();
66          messages.add(21);
67  
68          final SsrIgm01 igm01 = (SsrIgm01) new IgsSsrMessagesParser(messages, DataContext.getDefault().getTimeScales()).
69                                 parse(message, false);
70  
71          // Verify size
72          Assertions.assertEquals(1,                            igm01.getData().size());
73          Assertions.assertEquals(SatelliteSystem.GPS,          igm01.getSatelliteSystem());
74  
75          // Verify header
76          Assertions.assertEquals(21,                           igm01.getTypeCode());
77          Assertions.assertEquals(517695.0,                     igm01.getHeader().getSsrEpoch1s(), eps);
78          Assertions.assertEquals(5.0,                          igm01.getHeader().getSsrUpdateInterval(), eps);
79          Assertions.assertEquals(0,                            igm01.getHeader().getSsrMultipleMessageIndicator());
80          Assertions.assertEquals(7,                            igm01.getHeader().getIodSsr());
81          Assertions.assertEquals(3951,                         igm01.getHeader().getSsrProviderId());
82          Assertions.assertEquals(1,                            igm01.getHeader().getSsrSolutionId());
83          Assertions.assertEquals(0,                            igm01.getHeader().getCrsIndicator());
84          Assertions.assertEquals(1,                            igm01.getHeader().getNumberOfSatellites());
85  
86          // Verify data for satellite G12
87          final SsrIgm01Data g12 = igm01.getSsrIgm01Data().get("G12").get(0);
88          Assertions.assertEquals(12,                           g12.getSatelliteID());
89          Assertions.assertEquals(132,                          g12.getGnssIod());
90          Assertions.assertEquals(18.0095,                      g12.getOrbitCorrection().getDeltaOrbitRadial(),        eps);
91          Assertions.assertEquals(122.8668,                     g12.getOrbitCorrection().getDeltaOrbitAlongTrack(),    eps);
92          Assertions.assertEquals(122.8668,                     g12.getOrbitCorrection().getDeltaOrbitCrossTrack(),    eps);
93          Assertions.assertEquals(0.090047,                     g12.getOrbitCorrection().getDotOrbitDeltaRadial(),     eps);
94          Assertions.assertEquals(0.614332,                     g12.getOrbitCorrection().getDotOrbitDeltaAlongTrack(), eps);
95          Assertions.assertEquals(0.614332,                     g12.getOrbitCorrection().getDotOrbitDeltaCrossTrack(), eps);
96  
97      }
98  
99      @Test
100     public void testPerfectValueGalileo() {
101 
102         final String m = "010000100100" +                 // RTCM Message number: 1060
103                          "001" +                          // IGS SSR version
104                          "00111101" +                     // IGS Message number: 61 (Galileo)
105                          "01111110011000111111" +         // Epoch Time 1s
106                          "0111" +                         // SSR Update Interval
107                          "0" +                            // Multiple Message Indicator
108                          "0111" +                         // IOD SSR
109                          "0000111101101111" +             // SSR Provider ID
110                          "0001" +                         // SSR Solution ID
111                          "0" +                            // Global/Regional CRS Indicator
112                          "000001" +                       // No. of Satellites
113                          "000001" +                       // Satellite ID
114                          "10000100" +                     // GNSS IOD
115                          "0000101011111101111111" +       // Delta Radial
116                          "01001010111111011111" +         // Delta Along-Track
117                          "01001010111111011111" +         // Delta Cross-Track
118                          "000010101111110111111" +        // Dot Delta Radial
119                          "0100101011111101111" +          // Dot Delta Along-Track
120                          "010010101111110111100";         // Dot Delta Cross-Track
121 
122         final EncodedMessage message = new ByteArrayEncodedMessage(byteArrayFromBinary(m));
123         message.start();
124 
125         ArrayList<Integer> messages = new ArrayList<>();
126         messages.add(0);
127 
128         final SsrIgm01 igm01 = (SsrIgm01) new IgsSsrMessagesParser(messages, DataContext.getDefault().getTimeScales()).
129                                parse(message, false);
130 
131         // Verify size
132         Assertions.assertEquals(1,                            igm01.getData().size());
133         Assertions.assertEquals(SatelliteSystem.GALILEO,      igm01.getSatelliteSystem());
134 
135         // Verify header
136         Assertions.assertEquals(61,                           igm01.getTypeCode());
137         Assertions.assertEquals(517695.0,                     igm01.getHeader().getSsrEpoch1s(), eps);
138         Assertions.assertEquals(120.0,                        igm01.getHeader().getSsrUpdateInterval(), eps);
139         Assertions.assertEquals(0,                            igm01.getHeader().getSsrMultipleMessageIndicator());
140         Assertions.assertEquals(7,                            igm01.getHeader().getIodSsr());
141         Assertions.assertEquals(3951,                         igm01.getHeader().getSsrProviderId());
142         Assertions.assertEquals(1,                            igm01.getHeader().getSsrSolutionId());
143         Assertions.assertEquals(0,                            igm01.getHeader().getCrsIndicator());
144         Assertions.assertEquals(1,                            igm01.getHeader().getNumberOfSatellites());
145 
146         // Verify data for satellite E01
147         final SsrIgm01Data e01 = igm01.getSsrIgm01Data().get("E01").get(0);
148         Assertions.assertEquals(1,                            e01.getSatelliteID());
149         Assertions.assertEquals(132,                          e01.getGnssIod());
150         Assertions.assertEquals(18.0095,                      e01.getOrbitCorrection().getDeltaOrbitRadial(),        eps);
151         Assertions.assertEquals(122.8668,                     e01.getOrbitCorrection().getDeltaOrbitAlongTrack(),    eps);
152         Assertions.assertEquals(122.8668,                     e01.getOrbitCorrection().getDeltaOrbitCrossTrack(),    eps);
153         Assertions.assertEquals(0.090047,                     e01.getOrbitCorrection().getDotOrbitDeltaRadial(),     eps);
154         Assertions.assertEquals(0.614332,                     e01.getOrbitCorrection().getDotOrbitDeltaAlongTrack(), eps);
155         Assertions.assertEquals(0.614332,                     e01.getOrbitCorrection().getDotOrbitDeltaCrossTrack(), eps);
156 
157     }
158 
159     @Test
160     public void testNullMessage() {
161         final String m = "010000100100" +                 // RTCM Message number: 1060
162                         "001" +                          // IGS SSR version
163                         "11111111" +                     // IGS Message number: 21 (GPS)
164                         "01111110011000111111" +         // Epoch Time 1s
165                         "0101" +                         // SSR Update Interval
166                         "0" +                            // Multiple Message Indicator
167                         "0111" +                         // IOD SSR
168                         "0000111101101111" +             // SSR Provider ID
169                         "0001" +                         // SSR Solution ID
170                         "0" +                            // Global/Regional CRS Indicator
171                         "000001" +                       // No. of Satellites
172                         "001100" +                       // Satellite ID
173                         "10000100" +                     // GNSS IOD
174                         "0000101011111101111111" +       // Delta Radial
175                         "01001010111111011111" +         // Delta Along-Track
176                         "01001010111111011111" +         // Delta Cross-Track
177                         "000010101111110111111" +        // Dot Delta Radial
178                         "0100101011111101111" +          // Dot Delta Along-Track
179                         "010010101111110111100";         // Dot Delta Cross-Track
180 
181        final EncodedMessage message = new ByteArrayEncodedMessage(byteArrayFromBinary(m));
182        message.start();
183 
184        ArrayList<Integer> messages = new ArrayList<>();
185        messages.add(9999999);
186 
187        final SsrIgm01 igm01 = (SsrIgm01) new IgsSsrMessagesParser(messages, DataContext.getDefault().getTimeScales()).
188                               parse(message, true);
189 
190        Assertions.assertNull(igm01);
191     }
192 
193     @Test
194     public void testEmptyMessage() {
195         try {
196             final byte[] array = new byte[0];
197             final EncodedMessage emptyMessage = new ByteArrayEncodedMessage(array);
198             new IgsSsrMessagesParser(new ArrayList<>(), DataContext.getDefault().getTimeScales()).
199                 parse(emptyMessage, false);
200             Assertions.fail("an exception should have been thrown");
201         } catch (OrekitException oe) {
202             Assertions.assertEquals(OrekitMessages.END_OF_ENCODED_MESSAGE, oe.getSpecifier());
203         }
204 
205     }
206 
207     @Test
208     public void testDefaultSsrUpdateInterval() {
209         final EncodedMessage message = new ByteArrayEncodedMessage(byteArrayFromBinary("1111111111111111"));
210         Assertions.assertEquals(10800, IgsSsrDataField.IDF004.intValue(message));
211     }
212 
213     private byte[] byteArrayFromBinary(String radix2Value) {
214         final byte[] array = new byte[radix2Value.length() / 8];
215         for (int i = 0; i < array.length; ++i) {
216             for (int j = 0; j < 8; ++j) {
217                 if (radix2Value.charAt(8 * i + j) != '0') {
218                     array[i] |= 0x1 << (7 - j);
219                 }
220             }
221         }
222         return array;
223     }
224 
225 }