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 }